This is a software implementation for people without h/w vTPM support.
Signed-off-by: Vinnie Scarlata <vincent.r.scarlata@intel.com>
Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
Signed-off-by: Steven Hand <steven@xensource.com>
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
--- /dev/null
+XEN_ROOT = ../..
+
+# Base definitions and rules
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+SUBDIRS = crypto tcs util manager
+
+all: build
+
+build:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+install: build
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+clean:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
+mrproper:
+ @set -e; for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done
+
+
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+Directory Structure
+===================
+tools/vtpm_manager/crypto -> crypto files
+tools/vtpm_manager/TCS -> TCS implementation
+tools/vtpm_manager/util -> Utility Library. Include disk-io and buffers.
+tools/vtpm_manager/manager -> VTPM Manager
+
+Compile Flags
+===================
+LOGGING_MODULES -> How extensive logging happens
+ see util/log.h for more info
+
+VTPM_MULTI_VM -> Defined: VTPMs run in their own VMs
+ Not Defined (default): VTPMs are processes
+
+# Debugging flags that may disappear without notice in the future
+
+DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and
+ /tmp/out.fifo rather than backend
+
+MANUAL_DM_LAUNCH -> User must manually launch & kill VTPMs
+
+USE_FIXED_SRK_AUTH -> Do not randomly generate a random SRK & Owner auth
+
+Requirements
+============
+- xen-unstable
+- IBM frontend/backend vtpm driver patch
+
+Single-VM Flow
+============================
+- Launch the VTPM manager (vtpm_managerd) which which begins listening to the BE with one thread
+ and listens to a named fifo that is shared by the vtpms to commuincate with the manager.
+- VTPM Manager listens to TPM BE.
+- When xend launches a tpm frontend equipped VM it contacts the manager over the vtpm backend.
+- When the manager receives the open message from the BE, it launches a vtpm
+- Xend allows the VM to continue booting.
+- When a TPM request is issued to the front end, the front end transmits the TPM request to the backend.
+- The manager receives the TPM requests and uses a named fifo to forward the request to the vtpm.
+- The fifo listener begins listening for the reply from vtpm for the request.
+- Vtpm processes request and replies to manager over shared named fifo.
+- If needed, the vtpm may send a request to the vtpm_manager at any time to save it's secrets to disk.
+- Manager receives response from vtpm and passes it back to backend for forwarding to guest.
+
+NOTES:
+* SaveService SHOULD seal it's table before saving it to disk. However,
+ the current Xen infrastructure does not provide a mechanism for this to be
+ unsealed later. Specifically, the auth and wrapped key must be available ONLY
+ to the service, or it's not even worth encrypting
+
+ In the future the vtpm manager will be protected by an early boot mechanism
+ that will allow for better protection of it's data.
+
+TODO:
+- Timeout on crashed vtpms
+- create lock for shared fifo for talking to vtpms.
--- /dev/null
+# Base definitions and rules (XEN_ROOT must be defined in including Makefile)
+include $(XEN_ROOT)/tools/Rules.mk
+
+#
+# Tool definitions
+#
+
+# Installation program and options
+INSTALL = install
+INSTALL_PROG = $(INSTALL) -m0755
+INSTALL_DIR = $(INSTALL) -d -m0755
+
+# Xen tools installation directory
+TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
+
+# General compiler flags
+CFLAGS = -Wall -Werror -g3 -I.
+
+# For generating dependencies
+CFLAGS += -Wp,-MD,.$(@F).d
+
+DEP_FILES = .*.d
+
+# Generic project files
+HDRS = $(wildcard *.h)
+SRCS = $(wildcard *.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+# Generic (non-header) dependencies
+$(SRCS): Makefile $(XEN_ROOT)/tools/Rules.mk $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+$(OBJS): $(SRCS)
+
+-include $(DEP_FILES)
+
+# Make sure these are just rules
+.PHONY : all build install clean
+
+#
+# Project-specific definitions
+#
+
+# Logging Level. See utils/tools.h for usage
+CFLAGS += -DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM)|BITMASK(VTPM_LOG_VTPM_DEEP))"
+
+# Silent Mode
+#CFLAGS += -DLOGGING_MODULES=0x0
+#CFLAGS += -DLOGGING_MODULES=0xff
+
+# Use frontend/backend pairs between manager & DMs?
+#CFLAGS += -DVTPM_MULTI_VM
+
+# vtpm_manager listens on /tmp/in.fifo and /tmp/out.fifo rather than backend
+#CFLAGS += -DDUMMY_BACKEND
+
+# Do not have manager launch DMs.
+#CFLAGS += -DMANUAL_DM_LAUNCH
+
+# Fixed SRK
+CFLAGS += -DUSE_FIXED_SRK_AUTH
+
+# TPM Hardware Device or TPM Simulator
+#CFLAGS += -DTPM_HWDEV
+
+# Include
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util
+CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs
--- /dev/null
+XEN_ROOT = ../../..\r
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk\r
+\r
+BIN = libtcpaCrypto.a\r
+\r
+all: build\r
+\r
+build: $(BIN)\r
+\r
+install: build\r
+\r
+clean:\r
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)\r
+\r
+mrproper: clean\r
+\r
+$(BIN): $(OBJS)\r
+ $(AR) rcs $(BIN) $(OBJS)\r
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// crypto.c
+//
+// This file will handle all the TPM Crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "crypto.h"
+#include "log.h"
+
+/**
+ * Initialize cryptography library
+ * @rand: random seed
+ * @size: size of @rand
+ */
+void Crypto_Init(const BYTE* rand, int size) {
+ ERR_load_crypto_strings();
+ CRYPTO_malloc_init();
+ OpenSSL_add_all_algorithms();
+ SYM_CIPHER = EVP_aes_128_cbc();
+ RAND_poll();
+ if (rand == NULL)
+ return;
+
+ RAND_add(rand, size, size);
+}
+
+/**
+ * Shutdown cryptography library
+ */
+void Crypto_Exit() {
+ ERR_free_strings();
+ ERR_remove_state(0);
+ EVP_cleanup();
+}
+
+
+/**
+ * Get random data
+ * @data: (OUT) Random data
+ * @size: Size of @data
+ */
+void Crypto_GetRandom(void* data, int size) {
+ int result;
+
+ result = RAND_pseudo_bytes((BYTE*) data, size);
+
+ if (result <= 0)
+ vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n",
+ ERR_error_string (ERR_get_error(), NULL));
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// crypto.h
+//
+// This file defines the TPM Crypto API
+//
+// ==================================================================
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+#define CRYPTO_MAX_SIG_SIZE (2048 / 8)
+#define CRYPTO_MAX_RSA_KEY_SIZE (4096 / 8) //in bytes
+
+#define OAEP_P "TCPA"
+#define OAEP_P_SIZE 4
+
+// Algorithms supported by crypto. Stored in CRYPTO_INFO.algorithmID
+#define CRYPTO_ALGORITH_RSA 0x01
+
+// Supported Encryption Schemes CRYPTO_INFO.encScheme
+#define CRYPTO_ES_NONE 0x0001
+#define CRYPTO_ES_RSAESPKCSv15 0x0002
+#define CRYPTO_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// Supported Signature schemes CRYPTO_INFO.sigScheme
+#define CRYPTO_SS_NONE 0x0001
+#define CRYPTO_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define CRYPTO_SS_RSASSAPKCS1v15_DER 0x0003
+
+typedef struct CRYPTO_INFO {
+ void *keyInfo;
+ UINT32 algorithmID;
+ UINT32 encScheme;
+ UINT32 sigScheme;
+} CRYPTO_INFO;
+
+
+void Crypto_Init(const BYTE* rand, int size);
+
+void Crypto_Exit();
+
+void Crypto_GetRandom(void* data, int size);
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest);
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest); /* presumably of 20 bytes */
+
+void Crypto_SHA1Full( const BYTE* text,
+ UINT32 size,
+ BYTE* hash); //Complete 3part SHA1
+
+// o_hash needs to be large enough to hold the digest, ie 20 bytes
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_hash);
+
+void Crypto_SHA1Start(UINT32* maxNumBytes);
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData);
+void Crypto_SHA1Complete( int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue);
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys);
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ /*[OUT]*/ CRYPTO_INFO* cryptoInfo);
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo);
+
+//
+// symmetric pack and unpack operations
+//
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen);
+
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread);
+
+
+// return 0 on success, -1 on error
+int Crypto_RSAEnc( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSADec( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData);
+
+// return 0 on success, -1 on error
+int Crypto_RSASign( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig);
+
+bool Crypto_RSAVerify( CRYPTO_INFO *keys,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig);
+
+//private:
+int RSA_verify_DER(int dtype, unsigned char *m, unsigned int m_len,
+ unsigned char *sigbuf, unsigned int siglen, CRYPTO_INFO *key);
+
+int RSA_sign_DER(int type, unsigned char *m, unsigned int m_len,
+ unsigned char *sigret, unsigned int *siglen, CRYPTO_INFO *key);
+
+#endif // __CRYPTO_H__
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// hash.c
+//
+// This file will handle all the TPM Hash functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "tcg.h" // for TPM_SUCCESS
+#include "crypto.h"
+
+static SHA_CTX g_shaContext;
+
+void Crypto_HMAC( const BYTE* text,
+ int text_len,
+ const BYTE* key,
+ int key_len,
+ BYTE* digest) {
+ if (text == NULL || key == NULL || text_len == 0 || key_len == 0)
+ return;
+
+ HMAC(EVP_sha1(), key, key_len, text, text_len, digest, NULL);
+}
+
+TPM_RESULT Crypto_HMAC_buf (const buffer_t * text,
+ const buffer_t * key,
+ BYTE * o_digest) { /* presumably of 20 bytes */
+
+ Crypto_HMAC (text->bytes, text->size,
+ key->bytes, key->size,
+ o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * SHA1
+ * (OUT) Create a SHA1 hash of text. Calls all three SHA1 steps internally
+ */
+void Crypto_SHA1Full( const BYTE* text,
+ uint32_t size,
+ BYTE* hash) {
+
+ if (text == NULL || size == 0)
+ return;
+
+ // Run SHA1Start + SHAUpdate (if necessary) + SHAComplete
+ uint32_t maxBytes; // Not used for anything
+ Crypto_SHA1Start(&maxBytes);
+
+ while (size > 64){
+ Crypto_SHA1Update(64, text);
+ size -= 64;
+ text += 64;
+ }
+
+ Crypto_SHA1Complete(size, text, hash);
+}
+
+// same thing using buffer_t
+TPM_RESULT Crypto_SHA1Full_buf (const buffer_t * buf,
+ BYTE * o_digest) {
+
+ if (buf->bytes == NULL || buf->size == 0)
+ return TPM_BAD_PARAMETER;
+
+ Crypto_SHA1Full (buf->bytes, buf->size, o_digest);
+
+ return TPM_SUCCESS;
+}
+
+
+/*
+ * Initialize SHA1
+ * (OUT) Maximum number of bytes that can be sent to SHA1Update.
+ * Must be a multiple of 64 bytes.
+ */
+void Crypto_SHA1Start(uint32_t* maxNumBytes) {
+ int max = SHA_CBLOCK;
+ // Initialize the crypto library
+ SHA1_Init(&g_shaContext);
+ *maxNumBytes = max;
+}
+
+/*
+ * Process SHA1
+ * @numBytes: (IN) The number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Bytes to be hashed.
+ */
+void Crypto_SHA1Update(int numBytes, const BYTE* hashData) {
+
+ if (hashData == NULL || numBytes == 0 || numBytes%64 != 0)
+ return;
+
+ SHA1_Update(&g_shaContext, hashData, numBytes);
+}
+
+/*
+ * Complete the SHA1 process
+ * @hashDataSize: (IN) Number of bytes in hashData.
+ * Must be a multiple of 64 bytes.
+ * @hashData: (IN) Final bytes to be hashed.
+ * @hashValue: (OUT) The output of the SHA-1 hash.
+ */
+void Crypto_SHA1Complete(int hashDataSize,
+ const BYTE* hashData,
+ BYTE* hashValue) {
+ SHA1_Update(&g_shaContext, hashData, hashDataSize);
+ SHA1_Final(hashValue, &g_shaContext);
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// rsa.c
+//
+// This file will handle all the TPM RSA crypto functionality
+//
+// ==================================================================
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include <openssl/err.h>
+#include <stdio.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "crypto.h"
+#include "log.h"
+
+void Crypto_RSACreateKey( /*in*/ UINT32 keySize,
+ /*in*/ UINT32 pubExpSize,
+ /*in*/ BYTE *pubExp,
+ /*out*/ UINT32 *privExpSize,
+ /*out*/ BYTE *privExp,
+ /*out*/ UINT32 *modulusSize,
+ /*out*/ BYTE *modulus,
+ /*out*/ CRYPTO_INFO *keys) {
+ unsigned long e_value;
+
+ if (pubExpSize == 0) // Default e = 2^16+1
+ e_value = (0x01 << 16) + 1;
+ else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ e_value = (0x01 << 16) + 1;
+ }
+
+ RSA *rsa = RSA_generate_key(keySize, e_value, NULL, NULL);
+
+ if (keys) {
+ keys->keyInfo = rsa;
+ keys->algorithmID = CRYPTO_ALGORITH_RSA;
+ }
+
+ if (modulus) *modulusSize = BN_bn2bin(rsa->n, modulus);
+ if (privExp) *privExpSize = BN_bn2bin(rsa->d, privExp);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfo( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 privExpSize,
+ /*[IN]*/ BYTE *privExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+ rsa->d = BN_bin2bn(privExp, privExpSize, NULL);
+}
+
+// Create a CRYPTO_INFO struct from the BYTE * key parts.
+// If pubExp info is NULL, use TCG default.
+// If there is a remainder while calculating the privExp, return FALSE.
+
+void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize,
+ /*[IN]*/ BYTE *pubExp,
+ /*[IN]*/ UINT32 modulusSize,
+ /*[IN]*/ BYTE *modulus,
+ CRYPTO_INFO* cryptoInfo) {
+ cryptoInfo->keyInfo = RSA_new();
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ rsa->e = BN_new();
+
+ if (pubExpSize == 0) { // Default e = 2^16+1
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ } else {
+ // This is not supported, but the following line MIGHT work
+ // under then assumption that the format is BigNum compatable
+ // Though it's not in the spec, so who knows what it is.
+ // Forcing the default.
+ //BN_bin2bn(pubExp, pubExpSize, NULL);
+ BN_set_bit(rsa->e, 16);
+ BN_set_bit(rsa->e, 0);
+ }
+
+ rsa->n = BN_bin2bn(modulus, modulusSize, NULL);
+
+}
+
+int Crypto_RSAEnc( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ return -1;
+
+ *outDataSize = 0;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ if (RSA_padding_add_PKCS1_type_2(paddedData, paddedDataSize, inData, inDataSize) <= 0) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ if (RSA_padding_add_PKCS1_OAEP(paddedData,paddedDataSize,inData,inDataSize, (BYTE *) OAEP_P,OAEP_P_SIZE) <= 0 ) {
+ rc = -1;
+ goto abort_egress;
+ }
+ break;
+ default:
+ rc = -1;
+ goto abort_egress;
+ }
+
+ rc = RSA_public_encrypt(paddedDataSize, paddedData, outData, rsa, RSA_NO_PADDING);
+ if (rc == -1)
+ goto abort_egress;
+
+ *outDataSize = rc;
+
+ if (rc > 0) rc = 0;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ if (paddedData)
+ free (paddedData);
+ return rc;
+
+}
+
+int Crypto_RSADec( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *outDataSize,
+ /*out*/ BYTE *outData) {
+
+ RSA *rsa = (RSA *) key->keyInfo;
+ UINT32 paddedDataSize = RSA_size (rsa);
+ BYTE *paddedData = (BYTE *)malloc(sizeof(BYTE) * paddedDataSize);
+ int rc;
+
+ if (paddedData == NULL)
+ goto abort_egress;
+
+ rc = RSA_private_decrypt(inDataSize, inData, paddedData, rsa, RSA_NO_PADDING);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_private_decrypt: %s\n", ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+
+ paddedDataSize = rc;
+
+ switch (key->encScheme) {
+ case CRYPTO_ES_RSAESPKCSv15:
+ rc = RSA_padding_check_PKCS1_type_2 (outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa));
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_type_2: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ case CRYPTO_ES_RSAESOAEP_SHA1_MGF1:
+ rc = RSA_padding_check_PKCS1_OAEP(outData, paddedDataSize,
+ paddedData + 1, paddedDataSize - 1,
+ RSA_size(rsa),
+ (BYTE *) OAEP_P, OAEP_P_SIZE);
+ if (rc == -1) {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA_padding_check_PKCS1_OAEP: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto abort_egress;
+ }
+ *outDataSize = rc;
+ break;
+ default:
+ *outDataSize = 0;
+ }
+
+ free(paddedData); paddedData = NULL;
+ goto egress;
+
+ abort_egress:
+
+ if (paddedData)
+ free (paddedData);
+ return -1;
+
+ egress:
+ return 0;
+}
+
+// Signs either a SHA1 digest of a message or a DER encoding of a message
+// Textual messages MUST be encoded or Hashed before sending into this function
+// It will NOT SHA the message.
+int Crypto_RSASign( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ /*out*/ UINT32 *sigSize,
+ /*out*/ BYTE *sig) {
+ int status;
+ unsigned int intSigSize;
+
+ switch(key->sigScheme) {
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_sign(NID_sha1, inData, inDataSize, sig, &intSigSize, (RSA *) key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ // status = Crypto_RSA_sign_DER(NID_md5_sha1, inData, inDataSize, sig, &intSigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status == 0) {
+ *sigSize = 0;
+ vtpmlogerror(VTPM_LOG_CRYPTO, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+
+ *sigSize = (UINT32) intSigSize;
+ return 0;
+}
+
+bool Crypto_RSAVerify( CRYPTO_INFO *key,
+ UINT32 inDataSize,
+ BYTE *inData,
+ UINT32 sigSize,
+ BYTE *sig) {
+ int status;
+
+ switch(key->sigScheme){
+ case CRYPTO_SS_RSASSAPKCS1v15_SHA1:
+ status = RSA_verify(NID_sha1, inData, inDataSize, sig, sigSize, (RSA *) key->keyInfo);
+ break;
+ case CRYPTO_SS_RSASSAPKCS1v15_DER:
+ //status = Crypto_RSA_verify_DER(NID_md5_sha1, inData, inDataSize, sig, sigSize, key);
+ vtpmlogerror(VTPM_LOG_CRYPTO, "Crypto: Unimplemented sign type (%d)\n", key->sigScheme);
+ status = 0;
+ break;
+ default:
+ status = 0;
+ }
+
+ if (status)
+ return(1);
+ else {
+ vtpmlogerror(VTPM_LOG_CRYPTO, "RSA verify: %s\n", ERR_error_string(ERR_get_error(), NULL));
+ return(0);
+ }
+
+}
+
+// helper which packs everything into a BIO!
+
+// packs the parameters first, then the private key, then the public key
+// if *io_buf is NULL, allocate it here as needed. otherwise its size is in
+// *io_buflen
+TPM_RESULT Crypto_RSAPackCryptoInfo (const CRYPTO_INFO* cryptoInfo,
+ BYTE ** io_buf, UINT32 * io_buflen) {
+ TPM_RESULT status = TPM_SUCCESS;
+ BYTE * buf;
+ long len, outlen = *io_buflen;
+
+ const long PARAMSLEN = 3*sizeof(UINT32);
+
+ RSA *rsa = (RSA *) cryptoInfo->keyInfo;
+
+ BIO *mem = BIO_new(BIO_s_mem());
+
+
+ // write the openssl keys to the BIO
+ if ( i2d_RSAPrivateKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+ if ( i2d_RSAPublicKey_bio (mem, rsa) == 0 ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_SIZE);
+ }
+
+ // get the buffer out
+ len = BIO_get_mem_data (mem, &buf);
+
+ // see if we need to allocate a return buffer
+ if (*io_buf == NULL) {
+ *io_buf = (BYTE*) malloc (PARAMSLEN + len);
+ if (*io_buf == NULL)
+ ERRORDIE (TPM_SIZE);
+ } else { // *io_buf is already allocated
+ if (outlen < len + PARAMSLEN)
+ ERRORDIE (TPM_SIZE); // but not large enough!
+ }
+
+ // copy over the parameters (three UINT32's starting at algorithmID)
+ memcpy (*io_buf, &cryptoInfo->algorithmID, PARAMSLEN);
+
+ // copy over the DER keys
+ memcpy (*io_buf + PARAMSLEN, buf, len);
+
+ *io_buflen = len + PARAMSLEN;
+
+ goto egress;
+
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
+
+
+
+// sets up ci, and returns the number of bytes read in o_lenread
+TPM_RESULT Crypto_RSAUnpackCryptoInfo (CRYPTO_INFO * ci,
+ BYTE * in, UINT32 len,
+ UINT32 * o_lenread) {
+
+ TPM_RESULT status = TPM_SUCCESS;
+ long l;
+ BIO *mem;
+ RSA *rsa;
+
+ // first load up the params
+ l = 3 * sizeof(UINT32);
+ memcpy (&ci->algorithmID, in, l);
+ len -= l;
+ in += l;
+
+ // and now the openssl keys, private first
+ mem = BIO_new_mem_buf (in, len);
+
+ if ( (rsa = d2i_RSAPrivateKey_bio (mem, NULL)) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+ // now use the same RSA object and fill in the private key
+ if ( d2i_RSAPublicKey_bio (mem, &rsa) == NULL ) {
+ ERR_print_errors_fp (stderr);
+ ERRORDIE (TPM_BAD_PARAMETER);
+ }
+
+ ci->keyInfo = rsa; // needs to be freed somehow later
+
+ // FIXME: havent figured out yet how to tell how many bytes were read in the
+ // above oprations! so o_lenread is not set
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ BIO_free (mem);
+
+ return status;
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// sym_crypto.c
+//
+// Symmetric crypto portion of crypto
+//
+// ==================================================================
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include "tcg.h"
+#include "sym_crypto.h"
+
+typedef enum crypt_op_type_t {
+ CRYPT_ENCRYPT,
+ CRYPT_DECRYPT
+} crypt_op_type_t;
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype);
+
+
+// this is initialized in Crypto_Init()
+const EVP_CIPHER * SYM_CIPHER = NULL;
+
+const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0};
+
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init_copy (&key->key, keybits);
+ STATUSCHECK(status);
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
+ int res;
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // hmm, EVP_CIPHER_CTX_init does not return a value
+ EVP_CIPHER_CTX_init (&key->context);
+
+ key->cipher = SYM_CIPHER;
+
+ status = buffer_init (&key->key, EVP_CIPHER_key_length(key->cipher), NULL);
+ STATUSCHECK (status);
+
+ // and generate the key material
+ res = RAND_pseudo_bytes (key->key.bytes, key->key.size);
+ if (res < 0)
+ ERRORDIE (TPM_SHORTRANDOM);
+
+
+ goto egress;
+
+ abort_egress:
+ EVP_CIPHER_CTX_cleanup (&key->context);
+ buffer_free (&key->key);
+
+ egress:
+ return status;
+}
+
+
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV);
+
+ buffer_init (o_cipher,
+ clear->size +
+ EVP_CIPHER_iv_length(key->cipher) +
+ EVP_CIPHER_block_size (key->cipher),
+ 0);
+
+ // copy the IV into the front
+ buffer_copy (o_cipher, &iv);
+
+ // make an alias into which we'll put the ciphertext
+ buffer_init_alias (&cipher_alias, o_cipher, EVP_CIPHER_iv_length(key->cipher), 0);
+
+ status = ossl_symcrypto_op (key, clear, &iv, &cipher_alias, CRYPT_ENCRYPT);
+ STATUSCHECK (status);
+
+ // set the output size correctly
+ o_cipher->size += cipher_alias.size;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ buffer_t iv, cipher_alias;
+
+ // alias for the IV
+ buffer_init_alias (&iv, cipher, 0, EVP_CIPHER_iv_length(key->cipher));
+
+ // make an alias to where the ciphertext is, after the IV
+ buffer_init_alias (&cipher_alias, cipher, EVP_CIPHER_iv_length(key->cipher), 0);
+
+ // prepare the output buffer
+ status = buffer_init (o_clear,
+ cipher->size
+ - EVP_CIPHER_iv_length(key->cipher)
+ + EVP_CIPHER_block_size(key->cipher),
+ 0);
+ STATUSCHECK(status);
+
+ // and decrypt
+ status = ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CRYPT_DECRYPT);
+ STATUSCHECK (status);
+
+ goto egress;
+
+ abort_egress:
+ buffer_free (o_clear);
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) {
+ buffer_memset (&key->key, 0);
+ buffer_free (&key->key);
+
+ EVP_CIPHER_CTX_cleanup (&key->context);
+
+ return TPM_SUCCESS;
+}
+
+
+TPM_RESULT ossl_symcrypto_op (symkey_t* key,
+ const buffer_t* in,
+ const buffer_t* iv,
+ buffer_t * out,
+ crypt_op_type_t optype) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ int inlen, outlen;
+ tpm_size_t running;
+
+ if ( ! EVP_CipherInit_ex (&key->context,
+ key->cipher, NULL, key->key.bytes, iv->bytes,
+ optype == CRYPT_ENCRYPT ? 1 : 0) )
+ ERRORDIE (TPM_FAIL);
+
+
+
+ inlen = in->size;
+
+ outlen = 0;
+ running = 0;
+
+
+ if ( ! EVP_CipherUpdate (&key->context, out->bytes, &outlen, in->bytes, inlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ if ( ! EVP_CipherFinal_ex (&key->context, out->bytes + running, &outlen) )
+ ERRORDIE (TPM_FAIL);
+
+ running += outlen;
+
+ out->size = running;
+
+ goto egress;
+
+ abort_egress:
+ egress:
+
+ return status;
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// sym_crypto.h
+//
+// Symmetric Crypto
+//
+// ==================================================================
+
+#ifndef _SYM_CRYPTO_H
+#define _SYM_CRYPTO_H
+
+#include <openssl/evp.h>
+#include "buffer.h"
+
+typedef struct symkey_t {
+ buffer_t key;
+
+ EVP_CIPHER_CTX context;
+ const EVP_CIPHER * cipher;
+} symkey_t;
+
+extern const EVP_CIPHER * SYM_CIPHER;
+
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key);
+
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits);
+
+
+// these functions will allocate their output buffers
+TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
+ const buffer_t* clear,
+ buffer_t* o_cipher);
+
+TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
+ const buffer_t* cipher,
+ buffer_t* o_clear);
+
+// only free the internal parts, not the 'key' ptr
+TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key);
+
+#endif /* _SYM_CRYPTO_H */
--- /dev/null
+XEN_ROOT = ../../..\r
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk\r
+\r
+BIN = vtpm_managerd\r
+\r
+all: build\r
+\r
+build: $(BIN)\r
+\r
+install: build\r
+ if [ ! -d "$(DESTDIR)/var/vtpm/fifos" ]; \\r
+ then mkdir -p $(DESTDIR)/var/vtpm/fifos; \\r
+ fi\r
+ $(INSTALL_PROG) $(BIN) $(TOOLS_INSTALL_DIR)\r
+\r
+clean:\r
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)\r
+\r
+mrproper: clean\r
+ rm -f $(BIN)\r
+\r
+$(BIN): $(OBJS)\r
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@\r
+\r
+# libraries\r
+LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a\r
+LIBS += -lcrypto -lpthread -lrt -lm\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// dmictl.c\r
+// \r
+// Functions for creating and destroying DMIs\r
+//\r
+// ==================================================================\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <string.h>\r
+\r
+#ifndef VTPM_MUTLI_VM\r
+ #include <sys/types.h>\r
+ #include <sys/stat.h>\r
+ #include <fcntl.h>\r
+ #include <signal.h>\r
+ #include <wait.h>\r
+#endif\r
+\r
+#include "vtpmpriv.h"\r
+#include "bsg.h"\r
+#include "buffer.h"\r
+#include "log.h"\r
+#include "hashtable.h"\r
+#include "hashtable_itr.h"\r
+\r
+#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"\r
+\r
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res) {\r
+ TPM_RESULT status = TPM_FAIL;\r
+ \r
+ if (dmi_res == NULL) \r
+ return TPM_SUCCESS;\r
+ \r
+ status = TCS_CloseContext(dmi_res->TCSContext);\r
+ free ( dmi_res->NVMLocation );\r
+ dmi_res->connected = FALSE;\r
+\r
+#ifndef VTPM_MULTI_VM \r
+ free(dmi_res->guest_tx_fname);\r
+ free(dmi_res->vtpm_tx_fname);\r
+ \r
+ close(dmi_res->guest_tx_fh); dmi_res->guest_tx_fh = -1;\r
+ close(dmi_res->vtpm_tx_fh); dmi_res->vtpm_tx_fh = -1; \r
+ \r
+ \r
+ #ifndef MANUAL_DM_LAUNCH\r
+ if (dmi_res->dmi_id != VTPM_CTL_DM) {\r
+ if (dmi_res->dmi_pid != 0) {\r
+ vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid);\r
+ if ((kill(dmi_res->dmi_pid, SIGKILL) !=0) ||\r
+ (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid)){\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi on pid %d.\n", dmi_res->dmi_pid);\r
+ status = TPM_FAIL;\r
+ }\r
+ } else \r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was 0.\n");\r
+ }\r
+ #endif\r
+#endif\r
+\r
+ return status;\r
+}\r
+ \r
+TPM_RESULT VTPM_Handle_New_DMI( const buffer_t *param_buf) {\r
+ \r
+ VTPM_DMI_RESOURCE *new_dmi=NULL;\r
+ TPM_RESULT status=TPM_FAIL;\r
+ BYTE type;\r
+ UINT32 dmi_id, domain_id, *dmi_id_key; \r
+ int fh;\r
+\r
+#ifndef VTPM_MUTLI_VM\r
+ char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL\r
+ struct stat file_info;\r
+#endif\r
+ \r
+ if (param_buf == NULL) { // Assume creation of Dom 0 control\r
+ type = 0;\r
+ domain_id = VTPM_CTL_DM;\r
+ dmi_id = VTPM_CTL_DM;\r
+ } else if (buffer_len(param_buf) != sizeof(BYTE) + sizeof(UINT32) *2) {\r
+ vtpmloginfo(VTPM_LOG_VTPM, "New DMI command wrong length: %d.\n", buffer_len(param_buf));\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ } else {\r
+ BSG_UnpackList( param_buf->bytes, 3,\r
+ BSG_TYPE_BYTE, &type,\r
+ BSG_TYPE_UINT32, &domain_id,\r
+ BSG_TYPE_UINT32, &dmi_id);\r
+ }\r
+ \r
+ new_dmi = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id);\r
+ if (new_dmi == NULL) { \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Creating new DMI instance %d attached on domain %d.\n", dmi_id, domain_id);\r
+ // Brand New DMI. Initialize the persistent pieces\r
+ if ((new_dmi = (VTPM_DMI_RESOURCE *) malloc (sizeof(VTPM_DMI_RESOURCE))) == NULL) {\r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ }\r
+ memset(new_dmi, 0, sizeof(VTPM_DMI_RESOURCE));\r
+ new_dmi->dmi_id = dmi_id;\r
+ new_dmi->connected = FALSE;\r
+ \r
+ if ((dmi_id_key = (UINT32 *) malloc (sizeof(UINT32))) == NULL) {\r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ } \r
+ *dmi_id_key = new_dmi->dmi_id;\r
+ \r
+ // install into map\r
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){\r
+ free(new_dmi);\r
+ free(dmi_id_key);\r
+ status = TPM_FAIL;\r
+ goto egress;\r
+ }\r
+ \r
+ } else \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Re-attaching DMI instance %d on domain %d .\n", dmi_id, domain_id);\r
+ \r
+ if (new_dmi->connected) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Attempt to re-attach, currently attached instance %d. Ignoring\n", dmi_id);\r
+ status = TPM_BAD_PARAMETER;\r
+ goto egress;\r
+ }\r
+ \r
+ // Initialize the Non-persistent pieces\r
+ new_dmi->dmi_domain_id = domain_id;\r
+ new_dmi->NVMLocation = NULL;\r
+ \r
+ new_dmi->TCSContext = 0;\r
+ TPMTRYRETURN( TCS_OpenContext(&new_dmi->TCSContext) );\r
+ \r
+ new_dmi->NVMLocation = (char *) malloc(11 + strlen(DMI_NVM_FILE));\r
+ sprintf(new_dmi->NVMLocation, DMI_NVM_FILE, (uint32_t) new_dmi->dmi_id);\r
+ \r
+ // Measure DMI\r
+ // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value\r
+ /*\r
+ fh = open(TPM_EMULATOR_PATH, O_RDONLY);\r
+ stat_ret = fstat(fh, &file_stat);\r
+ if (stat_ret == 0) \r
+ dmi_size = file_stat.st_size;\r
+ else {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not open tpm_emulator!!\n");\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ dmi_buffer\r
+ */\r
+ memset(&new_dmi->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));\r
+ \r
+#ifndef VTPM_MULTI_VM\r
+ if (dmi_id != VTPM_CTL_DM) {\r
+ // Create a pair of fifo pipes\r
+ if( (new_dmi->guest_tx_fname = (char *) malloc(11 + strlen(GUEST_TX_FIFO))) == NULL){ \r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ }\r
+ sprintf(new_dmi->guest_tx_fname, GUEST_TX_FIFO, (uint32_t) dmi_id);\r
+ \r
+ if ((new_dmi->vtpm_tx_fname = (char *) malloc(11 + strlen(VTPM_TX_FIFO))) == NULL) {\r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ }\r
+ sprintf(new_dmi->vtpm_tx_fname, VTPM_TX_FIFO, (uint32_t) dmi_id);\r
+ \r
+ new_dmi->guest_tx_fh = -1;\r
+ new_dmi->vtpm_tx_fh= -1;\r
+ \r
+ if ( stat(new_dmi->guest_tx_fname, &file_info) == -1) {\r
+ if ( mkfifo(new_dmi->guest_tx_fname, S_IWUSR | S_IRUSR ) ){\r
+ status = TPM_FAIL;\r
+ goto abort_egress;\r
+ }\r
+ }\r
+ \r
+ if ( (fh = open(new_dmi->vtpm_tx_fname, O_RDWR)) == -1) {\r
+ if ( mkfifo(new_dmi->vtpm_tx_fname, S_IWUSR | S_IRUSR ) ) {\r
+ status = TPM_FAIL;\r
+ goto abort_egress;\r
+ }\r
+ }\r
+ \r
+ // Launch DMI\r
+ sprintf(dmi_id_str, "%d", (int) dmi_id);\r
+#ifdef MANUAL_DM_LAUNCH\r
+ vtpmlogerror(VTPM_LOG_VTPM, "FAKING starting vtpm with dmi=%s\n", dmi_id_str);\r
+ new_dmi->dmi_pid = 0;\r
+#else\r
+ pid_t pid = fork();\r
+ \r
+ if (pid == -1) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n");\r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ } else if (pid == 0) {\r
+ if ( stat(new_dmi->NVMLocation, &file_info) == -1)\r
+ execl (TPM_EMULATOR_PATH, "vtmpd", "clear", dmi_id_str, NULL);\r
+ else \r
+ execl (TPM_EMULATOR_PATH, "vtpmd", "save", dmi_id_str, NULL);\r
+ \r
+ // Returning from these at all is an error.\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n");\r
+ } else {\r
+ new_dmi->dmi_pid = pid;\r
+ vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);\r
+ }\r
+#endif // MANUAL_DM_LAUNCH\r
+ }\r
+#else // VTPM_MUTLI_VM\r
+ // FIXME: Measure DMI through call to Measurement agent in platform.\r
+#endif \r
+ \r
+ vtpm_globals->DMI_table_dirty = TRUE;\r
+ new_dmi->connected = TRUE; \r
+ status=TPM_SUCCESS;\r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ close_dmi( new_dmi );\r
+ \r
+ egress:\r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTPM_Handle_Close_DMI( const buffer_t *param_buf) {\r
+ \r
+ TPM_RESULT status=TPM_FAIL;\r
+ VTPM_DMI_RESOURCE *dmi_res=NULL;\r
+ UINT32 dmi_id;\r
+ \r
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ BSG_UnpackList( param_buf->bytes, 1,\r
+ BSG_TYPE_UINT32, &dmi_id);\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Closing DMI %d.\n", dmi_id);\r
+ \r
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi_id);\r
+ if (dmi_res == NULL ) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Trying to close nonexistent DMI.\n");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ if (!dmi_res->connected) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-connected DMI.\n");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ // Close Dmi\r
+ TPMTRYRETURN(close_dmi( dmi_res ));\r
+ \r
+ status=TPM_SUCCESS; \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ egress:\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) {\r
+ \r
+ TPM_RESULT status=TPM_FAIL;\r
+ VTPM_DMI_RESOURCE *dmi_res=NULL;\r
+ UINT32 dmi_id;\r
+ \r
+ if ((param_buf == NULL) || (buffer_len(param_buf) != sizeof(UINT32)) ) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing DMI has bad size.\n");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ BSG_UnpackList( param_buf->bytes, 1,\r
+ BSG_TYPE_UINT32, &dmi_id);\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Deleting DMI %d.\n", dmi_id); \r
+ \r
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_remove(vtpm_globals->dmi_map, &dmi_id);\r
+ if (dmi_res == NULL) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing non-existent DMI.\n");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ //TODO: Automatically delete file dmi_res->NVMLocation\r
+ \r
+ // Close DMI first\r
+ TPMTRYRETURN(close_dmi( dmi_res ));\r
+ free ( dmi_res );\r
+ \r
+ status=TPM_SUCCESS; \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ egress:\r
+ \r
+ return status;\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// securestorage.c\r
+// \r
+// Functions regarding securely storing DMI secrets.\r
+//\r
+// ==================================================================\r
+\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <unistd.h>\r
+#include <string.h>\r
+\r
+#include "tcg.h"\r
+#include "vtpm_manager.h"\r
+#include "vtpmpriv.h"\r
+#include "vtsp.h"\r
+#include "bsg.h"\r
+#include "crypto.h"\r
+#include "hashtable.h"\r
+#include "hashtable_itr.h"\r
+#include "buffer.h"\r
+#include "log.h"\r
+\r
+TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, \r
+ const buffer_t *inbuf, \r
+ buffer_t *outbuf) {\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ symkey_t symkey;\r
+ buffer_t state_cipher = NULL_BUF,\r
+ symkey_cipher = NULL_BUF;\r
+ int fh;\r
+ long bytes_written;\r
+ BYTE *sealed_NVM=NULL;\r
+ UINT32 sealed_NVM_size, i;\r
+ struct pack_constbuf_t symkey_cipher32, state_cipher32;\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));\r
+ for (i=0; i< buffer_len(inbuf); i++)\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ \r
+ // Generate a sym key and encrypt state with it\r
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );\r
+ TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &state_cipher) );\r
+ \r
+ // Encrypt symmetric key\r
+ TPMTRYRETURN( VTSP_Bind( &vtpm_globals->storageKey, \r
+ &symkey.key, \r
+ &symkey_cipher) );\r
+ \r
+ // Create output blob: symkey_size + symkey_cipher + state_cipher_size + state_cipher\r
+ \r
+ symkey_cipher32.size = buffer_len(&symkey_cipher);\r
+ symkey_cipher32.data = symkey_cipher.bytes;\r
+ \r
+ state_cipher32.size = buffer_len(&state_cipher);\r
+ state_cipher32.data = state_cipher.bytes;\r
+ \r
+ sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size + state_cipher32.size);\r
+ \r
+ sealed_NVM_size = BSG_PackList(sealed_NVM, 2,\r
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,\r
+ BSG_TPM_SIZE32_DATA, &state_cipher32);\r
+ \r
+ // Mark DMI Table so new save state info will get pushed to disk on return.\r
+ vtpm_globals->DMI_table_dirty = TRUE;\r
+ \r
+ // Write sealed blob off disk from NVMLocation\r
+ // TODO: How to properly return from these. Do we care if we return failure\r
+ // after writing the file? We can't get the old one back.\r
+ // TODO: Backup old file and try and recover that way.\r
+ fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);\r
+ if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long) sealed_NVM_size) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ close(fh);\r
+ \r
+ Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *) &myDMI->NVM_measurement); \r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));\r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");\r
+ \r
+ egress:\r
+ \r
+ buffer_free ( &state_cipher);\r
+ buffer_free ( &symkey_cipher);\r
+ free(sealed_NVM);\r
+ Crypto_symcrypto_freekey (&symkey);\r
+ \r
+ return status;\r
+}\r
+\r
+\r
+/* inbuf = null outbuf = sealed blob size, sealed blob.*/\r
+TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, \r
+ const buffer_t *inbuf, \r
+ buffer_t *outbuf) {\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ symkey_t symkey;\r
+ buffer_t state_cipher = NULL_BUF, \r
+ symkey_clear = NULL_BUF, \r
+ symkey_cipher = NULL_BUF;\r
+ struct pack_buf_t symkey_cipher32, state_cipher32;\r
+ \r
+ UINT32 sealed_NVM_size;\r
+ BYTE *sealed_NVM = NULL;\r
+ long fh_size;\r
+ int fh, stat_ret, i;\r
+ struct stat file_stat;\r
+ TPM_DIGEST sealedNVMHash;\r
+ \r
+ memset(&symkey, 0, sizeof(symkey_t));\r
+ \r
+ if (myDMI->NVMLocation == NULL) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name NULL.\n");\r
+ status = TPM_AUTHFAIL;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ //Read sealed blob off disk from NVMLocation\r
+ fh = open(myDMI->NVMLocation, O_RDONLY);\r
+ stat_ret = fstat(fh, &file_stat);\r
+ if (stat_ret == 0) \r
+ fh_size = file_stat.st_size;\r
+ else {\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ sealed_NVM = (BYTE *) malloc(fh_size);\r
+ if (read(fh, sealed_NVM, fh_size) != fh_size) {\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ close(fh);\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);\r
+ for (i=0; i< fh_size; i++)\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ \r
+ sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,\r
+ BSG_TPM_SIZE32_DATA, &symkey_cipher32,\r
+ BSG_TPM_SIZE32_DATA, &state_cipher32);\r
+ \r
+ TPMTRYRETURN( buffer_init_convert (&symkey_cipher, \r
+ symkey_cipher32.size, \r
+ symkey_cipher32.data) );\r
+ \r
+ TPMTRYRETURN( buffer_init_convert (&state_cipher, \r
+ state_cipher32.size, \r
+ state_cipher32.data) );\r
+ \r
+ Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash); \r
+ \r
+ // Verify measurement of sealed blob.\r
+ if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadNVM NVM measurement check failed.\n");\r
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");\r
+ for (i=0; i< sizeof(TPM_DIGEST); i++)\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&myDMI->NVM_measurement)[i]);\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+\r
+ vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");\r
+ for (i=0; i< sizeof(TPM_DIGEST); i++)\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]);\r
+ vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ \r
+ status = TPM_AUTHFAIL;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ // Decrypt Symmetric Key\r
+ TPMTRYRETURN( VTSP_Unbind( myDMI->TCSContext,\r
+ vtpm_globals->storageKeyHandle,\r
+ &symkey_cipher,\r
+ (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,\r
+ &symkey_clear,\r
+ &(vtpm_globals->keyAuth) ) );\r
+ \r
+ // create symmetric key using saved bits\r
+ Crypto_symcrypto_initkey (&symkey, &symkey_clear);\r
+ \r
+ // Decrypt State\r
+ TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher, outbuf) );\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");\r
+ \r
+ egress:\r
+ \r
+ buffer_free ( &state_cipher);\r
+ buffer_free ( &symkey_clear);\r
+ buffer_free ( &symkey_cipher);\r
+ free( sealed_NVM );\r
+ Crypto_symcrypto_freekey (&symkey);\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTPM_SaveService(void) {\r
+ TPM_RESULT status=TPM_SUCCESS;\r
+ int fh, dmis=-1;\r
+ \r
+ BYTE *flat_global;\r
+ int flat_global_size, bytes_written;\r
+ UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);\r
+ struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes};\r
+ \r
+ struct hashtable_itr *dmi_itr;\r
+ VTPM_DMI_RESOURCE *dmi_res;\r
+ \r
+ UINT32 flat_global_full_size;\r
+ \r
+ // Global Values needing to be saved\r
+ flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths\r
+ sizeof(UINT32) + // storagekeysize\r
+ storageKeySize + // storage key\r
+ hashtable_count(vtpm_globals->dmi_map) * // num DMIS\r
+ (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info\r
+ \r
+ \r
+ flat_global = (BYTE *) malloc( flat_global_full_size);\r
+ \r
+ flat_global_size = BSG_PackList(flat_global, 4,\r
+ BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,\r
+ BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,\r
+ BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,\r
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);\r
+ \r
+ // Per DMI values to be saved\r
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {\r
+ \r
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);\r
+ do {\r
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);\r
+ dmis++;\r
+\r
+ // No need to save dmi0.\r
+ if (dmi_res->dmi_id == 0) \r
+ continue;\r
+ \r
+ \r
+ flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,\r
+ BSG_TYPE_UINT32, &dmi_res->dmi_id,\r
+ BSG_TPM_DIGEST, &dmi_res->NVM_measurement,\r
+ BSG_TPM_DIGEST, &dmi_res->DMI_measurement);\r
+ \r
+ } while (hashtable_iterator_advance(dmi_itr));\r
+ }\r
+ \r
+ //FIXME: Once we have a way to protect a TPM key, we should use it to \r
+ // encrypt this blob. BUT, unless there is a way to ensure the key is\r
+ // not used by other apps, this encryption is useless.\r
+ fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);\r
+ if (fh == -1) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE);\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ if ( (bytes_written = write(fh, flat_global, flat_global_size)) != flat_global_size ) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes written.\n", bytes_written, flat_global_size);\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ vtpm_globals->DMI_table_dirty = FALSE; \r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ egress:\r
+ \r
+ free(flat_global);\r
+ close(fh);\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis = %d)\n", (int) status, dmis);\r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTPM_LoadService(void) {\r
+ \r
+ TPM_RESULT status=TPM_SUCCESS;\r
+ int fh, stat_ret, dmis=0;\r
+ long fh_size = 0, step_size;\r
+ BYTE *flat_global=NULL;\r
+ struct pack_buf_t storage_key_pack;\r
+ UINT32 *dmi_id_key;\r
+ \r
+ VTPM_DMI_RESOURCE *dmi_res;\r
+ struct stat file_stat;\r
+ \r
+ fh = open(STATE_FILE, O_RDONLY );\r
+ stat_ret = fstat(fh, &file_stat);\r
+ if (stat_ret == 0) \r
+ fh_size = file_stat.st_size;\r
+ else {\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ flat_global = (BYTE *) malloc(fh_size);\r
+ \r
+ if ((long) read(fh, flat_global, fh_size) != fh_size ) {\r
+ status = TPM_IOERROR;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ // Global Values needing to be saved\r
+ step_size = BSG_UnpackList( flat_global, 4,\r
+ BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,\r
+ BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,\r
+ BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,\r
+ BSG_TPM_SIZE32_DATA, &storage_key_pack);\r
+ \r
+ TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );\r
+ TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) );\r
+ \r
+ // Per DMI values to be saved\r
+ while ( step_size < fh_size ){\r
+ if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Encountered %ld extra bytes at end of manager state.\n", fh_size-step_size);\r
+ step_size = fh_size;\r
+ } else {\r
+ dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));\r
+ dmis++;\r
+ \r
+ dmi_res->connected = FALSE;\r
+ \r
+ step_size += BSG_UnpackList(flat_global + step_size, 3,\r
+ BSG_TYPE_UINT32, &dmi_res->dmi_id, \r
+ BSG_TPM_DIGEST, &dmi_res->NVM_measurement,\r
+ BSG_TPM_DIGEST, &dmi_res->DMI_measurement);\r
+ \r
+ // install into map\r
+ dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));\r
+ *dmi_id_key = dmi_res->dmi_id;\r
+ if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {\r
+ status = TPM_FAIL;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data\n");\r
+ egress:\r
+ \r
+ if (flat_global)\r
+ free(flat_global);\r
+ close(fh);\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Previously saved state reloaded (status = %d, dmis = %d).\n", (int) status, dmis);\r
+ return status;\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// tpmpassthrough.c\r
+// \r
+// Functions regarding passing DMI requests to HWTPM\r
+//\r
+// ==================================================================\r
+\r
+#include "tcg.h"\r
+#include "vtpm_manager.h"\r
+#include "vtpmpriv.h"\r
+#include "vtsp.h"\r
+#include "log.h"\r
+\r
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi,\r
+ buffer_t *inbuf, \r
+ buffer_t *outbuf) {\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE *ord; \r
+ \r
+ ord = (TPM_COMMAND_CODE *) (inbuf->bytes + sizeof(TPM_TAG) + sizeof(UINT32));\r
+ \r
+ switch (*ord) {\r
+ \r
+ // Forbidden for DMI use\r
+ case TPM_ORD_TakeOwnership:\r
+ case TPM_ORD_ChangeAuthOwner:\r
+ case TPM_ORD_DirWriteAuth:\r
+ case TPM_ORD_DirRead:\r
+ case TPM_ORD_AuthorizeMigrationKey:\r
+ case TPM_ORD_CreateMaintenanceArchive:\r
+ case TPM_ORD_LoadMaintenanceArchive:\r
+ case TPM_ORD_KillMaintenanceFeature:\r
+ case TPM_ORD_LoadManuMaintPub:\r
+ case TPM_ORD_ReadManuMaintPub:\r
+ case TPM_ORD_SelfTestFull:\r
+ case TPM_ORD_SelfTestStartup:\r
+ case TPM_ORD_CertifySelfTest:\r
+ case TPM_ORD_ContinueSelfTest:\r
+ case TPM_ORD_GetTestResult:\r
+ case TPM_ORD_Reset:\r
+ case TPM_ORD_OwnerClear:\r
+ case TPM_ORD_DisableOwnerClear:\r
+ case TPM_ORD_ForceClear:\r
+ case TPM_ORD_DisableForceClear:\r
+ case TPM_ORD_GetCapabilityOwner:\r
+ case TPM_ORD_OwnerSetDisable:\r
+ case TPM_ORD_PhysicalEnable:\r
+ case TPM_ORD_PhysicalDisable:\r
+ case TPM_ORD_SetOwnerInstall:\r
+ case TPM_ORD_PhysicalSetDeactivated:\r
+ case TPM_ORD_SetTempDeactivated:\r
+ case TPM_ORD_CreateEndorsementKeyPair:\r
+ case TPM_ORD_GetAuditEvent:\r
+ case TPM_ORD_GetAuditEventSigned:\r
+ case TPM_ORD_GetOrdinalAuditStatus:\r
+ case TPM_ORD_SetOrdinalAuditStatus:\r
+ case TPM_ORD_SetRedirection:\r
+ case TPM_ORD_FieldUpgrade:\r
+ case TSC_ORD_PhysicalPresence:\r
+ status = TPM_DISABLED_CMD;\r
+ goto abort_egress;\r
+ break;\r
+ \r
+ } // End ORD Switch\r
+ \r
+ // Call TCS with command\r
+ \r
+ TPMTRY(TPM_IOERROR, VTSP_RawTransmit( dmi->TCSContext,inbuf, outbuf) );\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ vtpmloginfo(VTPM_LOG_VTPM, "TPM Command Failed in tpmpassthrough.\n");\r
+ egress:\r
+ \r
+ return status;\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtpm_manager.c\r
+// \r
+// This file will house the main logic of the VTPM Manager\r
+//\r
+// ==================================================================\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <string.h>\r
+\r
+#ifndef VTPM_MULTI_VM\r
+#include <pthread.h>\r
+#include <errno.h>\r
+#include <aio.h>\r
+#include <time.h>\r
+#endif\r
+\r
+#include "vtpm_manager.h"\r
+#include "vtpmpriv.h"\r
+#include "vtsp.h"\r
+#include "bsg.h"\r
+#include "hashtable.h"\r
+#include "hashtable_itr.h"\r
+\r
+#include "log.h"\r
+#include "buffer.h"\r
+\r
+VTPM_GLOBALS *vtpm_globals=NULL;\r
+\r
+#ifdef VTPM_MULTI_VM\r
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, fmt, ##args );\r
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module, fmt, ##args );\r
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, fmt, ##args );\r
+#else \r
+ #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, "[%d]: " fmt, threadType, ##args );\r
+ #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module, fmt, ##args );\r
+ #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[%d]: " fmt, threadType, ##args );\r
+#endif\r
+\r
+// --------------------------- Static Auths --------------------------\r
+#ifdef USE_FIXED_SRK_AUTH\r
+\r
+static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+\r
+static BYTE FIXED_EK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+\r
+#endif\r
+ \r
+// -------------------------- Hash table functions --------------------\r
+\r
+static unsigned int hashfunc32(void *ky) {\r
+ return (* (UINT32 *) ky);\r
+}\r
+\r
+static int equals32(void *k1, void *k2) {\r
+ return (*(UINT32 *) k1 == *(UINT32 *) k2);\r
+}\r
+\r
+// --------------------------- Functions ------------------------------\r
+\r
+TPM_RESULT VTPM_Create_Service(){\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ \r
+ // Generate Auth's for SRK & Owner\r
+#ifdef USE_FIXED_SRK_AUTH\r
+ memcpy(vtpm_globals->owner_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));\r
+ memcpy(vtpm_globals->srk_usage_auth, FIXED_EK_AUTH, sizeof(TPM_AUTHDATA));\r
+#else \r
+ Crypto_GetRandom(vtpm_globals->owner_usage_auth, sizeof(TPM_AUTHDATA) );\r
+ Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) ); \r
+#endif\r
+ \r
+ // Take Owership of TPM\r
+ CRYPTO_INFO ek_cryptoInfo;\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");\r
+ status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);\r
+ \r
+ // If we can read PubEK then there is no owner and we should take it.\r
+ if (status == TPM_SUCCESS) { \r
+ TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,\r
+ (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, \r
+ (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,\r
+ &ek_cryptoInfo,\r
+ &vtpm_globals->keyAuth)); \r
+ \r
+ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,\r
+ (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, \r
+ &vtpm_globals->keyAuth)); \r
+ }\r
+ \r
+ // Generate storage key's auth\r
+ Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth, \r
+ sizeof(TPM_AUTHDATA) );\r
+ \r
+ TCS_AUTH osap;\r
+ TPM_AUTHDATA sharedsecret;\r
+ \r
+ TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,\r
+ TPM_ET_SRK,\r
+ 0, \r
+ (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,\r
+ &sharedsecret, \r
+ &osap) ); \r
+ \r
+ TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,\r
+ TPM_KEY_BIND,\r
+ (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,\r
+ TPM_SRK_KEYHANDLE, \r
+ (const TPM_AUTHDATA*)&sharedsecret,\r
+ &vtpm_globals->storageKeyWrap,\r
+ &osap) );\r
+ \r
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ exit(1);\r
+ \r
+ egress:\r
+ vtpmloginfo(VTPM_LOG_VTPM, "New VTPM Service initialized (Status = %d).\n", status);\r
+ return status;\r
+ \r
+}\r
+\r
+\r
+//////////////////////////////////////////////////////////////////////////////\r
+#ifdef VTPM_MULTI_VM\r
+int VTPM_Service_Handler(){\r
+#else\r
+void *VTPM_Service_Handler(void *threadTypePtr){\r
+#endif\r
+ TPM_RESULT status = TPM_FAIL; // Should never return\r
+ UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, out_message_size_full, dmi_cmd_size;\r
+ BYTE *cmd_header, *in_param, *out_message, *dmi_cmd;\r
+ buffer_t *command_buf=NULL, *result_buf=NULL;\r
+ TPM_TAG tag;\r
+ TPM_COMMAND_CODE ord;\r
+ VTPM_DMI_RESOURCE *dmi_res;\r
+ int size_read, size_write, i;\r
+ \r
+#ifndef VTPM_MULTI_VM\r
+ int threadType = *(int *) threadTypePtr;\r
+ \r
+ // async io structures\r
+ struct aiocb dmi_aio;\r
+ struct aiocb *dmi_aio_a[1];\r
+ dmi_aio_a[0] = &dmi_aio;\r
+#endif\r
+ \r
+#ifdef DUMMY_BACKEND\r
+ int dummy_rx; \r
+#endif\r
+ \r
+ // TODO: Reinsert ifdefs to enable support for MULTI-VM \r
+ \r
+ cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV);\r
+ command_buf = (buffer_t *) malloc(sizeof(buffer_t));\r
+ result_buf = (buffer_t *) malloc(sizeof(buffer_t));\r
+ \r
+#ifndef VTPM_MULTI_VM\r
+ TPM_RESULT *ret_value = (TPM_RESULT *) malloc(sizeof(TPM_RESULT));\r
+#endif\r
+ \r
+ int *tx_fh, *rx_fh;\r
+ \r
+#ifdef VTPM_MULTI_VM\r
+ rx_fh = &vtpm_globals->be_fh;\r
+#else\r
+ if (threadType == BE_LISTENER_THREAD) {\r
+#ifdef DUMMY_BACKEND \r
+ dummy_rx = -1;\r
+ rx_fh = &dummy_rx;\r
+#else\r
+ rx_fh = &vtpm_globals->be_fh;\r
+#endif\r
+ } else { // DMI_LISTENER_THREAD\r
+ rx_fh = &vtpm_globals->vtpm_rx_fh;\r
+ }\r
+#endif\r
+ \r
+#ifndef VTPM_MULTI_VM\r
+ int fh;\r
+ if (threadType == BE_LISTENER_THREAD) {\r
+ tx_fh = &vtpm_globals->be_fh;\r
+ if ( (fh = open(GUEST_RX_FIFO, O_RDWR)) == -1) {\r
+ if ( mkfifo(GUEST_RX_FIFO, S_IWUSR | S_IRUSR ) ){\r
+ *ret_value = TPM_FAIL;\r
+ pthread_exit(ret_value);\r
+ }\r
+ } else \r
+ close(fh);\r
+ \r
+ } else { // else DMI_LISTENER_THREAD\r
+ // tx_fh will be set once the DMI is identified\r
+ // But we need to make sure the read pip is created.\r
+ if ( (fh = open(VTPM_RX_FIFO, O_RDWR)) == -1) {\r
+ if ( mkfifo(VTPM_RX_FIFO, S_IWUSR | S_IRUSR ) ){\r
+ *ret_value = TPM_FAIL;\r
+ pthread_exit(ret_value);\r
+ }\r
+ } else \r
+ close(fh);\r
+ \r
+ }\r
+#endif\r
+ \r
+ while(1) {\r
+ \r
+ if (threadType == BE_LISTENER_THREAD) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for Guest requests & ctrl messages.\n");\r
+ } else \r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Waiting for DMI messages.\n");\r
+ \r
+ \r
+ if (*rx_fh < 0) {\r
+ if (threadType == BE_LISTENER_THREAD) \r
+#ifdef DUMMY_BACKEND\r
+ *rx_fh = open("/tmp/in.fifo", O_RDWR);\r
+#else\r
+ *rx_fh = open(VTPM_BE_DEV, O_RDWR);\r
+#endif\r
+ else // DMI Listener \r
+ *rx_fh = open(VTPM_RX_FIFO, O_RDWR);\r
+ \r
+ }\r
+ \r
+ if (*rx_fh < 0) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");\r
+#ifdef VTPM_MULTI_VM\r
+ return TPM_IOERROR; \r
+#else\r
+ *ret_value = TPM_IOERROR;\r
+ pthread_exit(ret_value);\r
+#endif\r
+ }\r
+ \r
+ size_read = read(*rx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);\r
+ if (size_read > 0) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV[%d}: 0x", size_read);\r
+ for (i=0; i<size_read; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);\r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't read from BE. Aborting... \n");\r
+ close(*rx_fh);\r
+ *rx_fh = -1;\r
+ goto abort_command;\r
+ }\r
+\r
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "\n");\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command shorter than normal header (%d bytes). Aborting...\n", size_read);\r
+ goto abort_command;\r
+ }\r
+ \r
+ BSG_UnpackList(cmd_header, 4,\r
+ BSG_TYPE_UINT32, &dmi,\r
+ BSG_TPM_TAG, &tag,\r
+ BSG_TYPE_UINT32, &in_param_size,\r
+ BSG_TPM_COMMAND_CODE, &ord );\r
+ \r
+ // Note that in_param_size is in the client's context\r
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;\r
+ if (cmd_size > 0) {\r
+ in_param = (BYTE *) malloc(cmd_size);\r
+ size_read = read( *rx_fh, in_param, cmd_size);\r
+ if (size_read > 0) {\r
+ for (i=0; i<size_read; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);\r
+ \r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. Aborting... \n");\r
+ close(*rx_fh);\r
+ *rx_fh = -1;\r
+ goto abort_command;\r
+ }\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ \r
+ if (size_read < (int) cmd_size) {\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) is shorter than header indicates(%d). Aborting...\n", size_read, cmd_size);\r
+ goto abort_command;\r
+ }\r
+ } else {\r
+ in_param = NULL;\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ } \r
+ \r
+ if ((threadType != BE_LISTENER_THREAD) && (dmi == 0)) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to access dom0 commands from DMI interface. Aborting...\n");\r
+ goto abort_command;\r
+ }\r
+ \r
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi);\r
+ if (dmi_res == NULL) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to non-existent DMI in domain: %d. Aborting...\n", dmi);\r
+ goto abort_command;\r
+ }\r
+ if (!dmi_res->connected) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempted access to disconnected DMI in domain: %d. Aborting...\n", dmi);\r
+ goto abort_command;\r
+ }\r
+ \r
+ if (threadType != BE_LISTENER_THREAD) \r
+ tx_fh = &dmi_res->vtpm_tx_fh;\r
+ // else we set this before the while loop since it doesn't change.\r
+ \r
+ if ( (buffer_init_convert(command_buf, cmd_size, in_param) != TPM_SUCCESS) || \r
+ (buffer_init(result_buf, 0, 0) != TPM_SUCCESS) ) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. Aborting...\n");\r
+ goto abort_command;\r
+ }\r
+ \r
+ // Dispatch it as either control or user request.\r
+ if (tag == VTPM_TAG_REQ) { \r
+ if (dmi_res->dmi_id == VTPM_CTL_DM){ \r
+ switch (ord) {\r
+ case VTPM_ORD_OPEN:\r
+ status = VTPM_Handle_New_DMI(command_buf);\r
+ break;\r
+ \r
+ case VTPM_ORD_CLOSE:\r
+ status = VTPM_Handle_Close_DMI(command_buf);\r
+ break;\r
+ \r
+ case VTPM_ORD_DELETE:\r
+ status = VTPM_Handle_Delete_DMI(command_buf);\r
+ break;\r
+ default:\r
+ status = TPM_BAD_ORDINAL; \r
+ } // switch\r
+ } else {\r
+ \r
+ switch (ord) { \r
+ case VTPM_ORD_SAVENVM:\r
+ status= VTPM_Handle_Save_NVM(dmi_res,\r
+ command_buf, \r
+ result_buf);\r
+ break;\r
+ case VTPM_ORD_LOADNVM:\r
+ status= VTPM_Handle_Load_NVM(dmi_res, \r
+ command_buf, \r
+ result_buf);\r
+ break;\r
+ \r
+ case VTPM_ORD_TPMCOMMAND:\r
+ status= VTPM_Handle_TPM_Command(dmi_res, \r
+ command_buf, \r
+ result_buf);\r
+ break;\r
+ \r
+ default:\r
+ status = TPM_BAD_ORDINAL; \r
+ } // switch\r
+ }\r
+ } else { // This is not a VTPM Command at all\r
+ \r
+ if (threadType == BE_LISTENER_THREAD) {\r
+ if (dmi == 0) {\r
+ // This usually indicates a FE/BE driver.\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Illegal use of TPM command from dom0\n");\r
+ status = TPM_FAIL;\r
+ } else {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Forwarding command to DMI.\n");\r
+ \r
+ if (dmi_res->guest_tx_fh < 0)\r
+ dmi_res->guest_tx_fh = open(dmi_res->guest_tx_fname, O_WRONLY | O_NONBLOCK);\r
+ \r
+ if (dmi_res->guest_tx_fh < 0){\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound fh to dmi.\n");\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ } \r
+ \r
+ //Note: Send message + dmi_id\r
+ if (cmd_size) {\r
+ dmi_cmd = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size);\r
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size;\r
+ memcpy(dmi_cmd, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);\r
+ memcpy(dmi_cmd + VTPM_COMMAND_HEADER_SIZE_SRV, in_param, cmd_size);\r
+ size_write = write(dmi_res->guest_tx_fh, dmi_cmd, dmi_cmd_size);\r
+ \r
+ if (size_write > 0) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT (DMI): 0x");\r
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV + cmd_size; i++) {\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", dmi_cmd[i]);\r
+ }\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI. Aborting... \n");\r
+ close(dmi_res->guest_tx_fh);\r
+ dmi_res->guest_tx_fh = -1;\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ free(dmi_cmd);\r
+ } else {\r
+ dmi_cmd_size = VTPM_COMMAND_HEADER_SIZE_SRV;\r
+ size_write = write(dmi_res->guest_tx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV );\r
+ if (size_write > 0) {\r
+ for (i=0; i<VTPM_COMMAND_HEADER_SIZE_SRV; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);\r
+ \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to DMI. Aborting... \n");\r
+ close(dmi_res->guest_tx_fh);\r
+ dmi_res->guest_tx_fh = -1;\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ }\r
+ \r
+ if (size_write != (int) dmi_cmd_size) \r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Could not write entire command to DMI (%d/%d)\n", size_write, dmi_cmd_size);\r
+ buffer_free(command_buf);\r
+ \r
+ if (vtpm_globals->guest_rx_fh < 0) \r
+ vtpm_globals->guest_rx_fh = open(GUEST_RX_FIFO, O_RDONLY);\r
+ \r
+ if (vtpm_globals->guest_rx_fh < 0){\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh to dmi.\n");\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ } \r
+ \r
+ size_read = read( vtpm_globals->guest_rx_fh, cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);\r
+ if (size_read > 0) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "RECV (DMI): 0x");\r
+ for (i=0; i<size_read; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);\r
+ \r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from DMI. Aborting... \n");\r
+ close(vtpm_globals->guest_rx_fh);\r
+ vtpm_globals->guest_rx_fh = -1;\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ \r
+ if (size_read < (int) VTPM_COMMAND_HEADER_SIZE_SRV) {\r
+ //vtpmdeepsublog("\n");\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command from DMI shorter than normal header. Aborting...\n");\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ \r
+ BSG_UnpackList(cmd_header, 4,\r
+ BSG_TYPE_UINT32, &dmi,\r
+ BSG_TPM_TAG, &tag,\r
+ BSG_TYPE_UINT32, &in_param_size,\r
+ BSG_TPM_COMMAND_CODE, &status );\r
+ \r
+ // Note that in_param_size is in the client's context\r
+ cmd_size = in_param_size - VTPM_COMMAND_HEADER_SIZE_CLT;\r
+ if (cmd_size > 0) {\r
+ in_param = (BYTE *) malloc(cmd_size);\r
+ size_read = read( vtpm_globals->guest_rx_fh, in_param, cmd_size);\r
+ if (size_read > 0) {\r
+ for (i=0; i<size_read; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[i]);\r
+ \r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error reading from BE. Aborting... \n");\r
+ close(vtpm_globals->guest_rx_fh);\r
+ vtpm_globals->guest_rx_fh = -1;\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");\r
+ \r
+ if (size_read < (int)cmd_size) {\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Command read(%d) from DMI is shorter than header indicates(%d). Aborting...\n", size_read, cmd_size);\r
+ status = TPM_IOERROR;\r
+ goto abort_with_error;\r
+ }\r
+ } else {\r
+ in_param = NULL;\r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM, "\n");\r
+ }\r
+ \r
+ if (buffer_init_convert(result_buf, cmd_size, in_param) != TPM_SUCCESS) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. Aborting...\n");\r
+ status = TPM_FAIL;\r
+ goto abort_with_error;\r
+ }\r
+ \r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM, "Sending DMI's response to guest.\n");\r
+ } // end else for if (dmi==0)\r
+ \r
+ } else { // This is a DMI lister thread. Thus this is from a DMI\r
+#ifdef VTPM_MULTI_VM\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Attempt to use unsupported direct access to TPM.\n");\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "Bad Command. dmi:%d, tag:%d, size:%d, ord:%d, Params: ", dmi, tag, in_param_size, ord);\r
+ for (UINT32 q=0; q<cmd_size; q++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", in_param[q]);\r
+ \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n");\r
+ \r
+ status = TPM_FAIL;\r
+#else\r
+ \r
+#endif\r
+ } // end else for if BE Listener\r
+ } // end else for is VTPM Command\r
+ \r
+ // Send response to Backend\r
+ if (*tx_fh < 0) {\r
+ if (threadType == BE_LISTENER_THREAD) \r
+#ifdef DUMMY_BACKEND\r
+ *tx_fh = open("/tmp/out.fifo", O_RDWR);\r
+#else\r
+ *tx_fh = open(VTPM_BE_DEV, O_RDWR);\r
+#endif\r
+ else // DMI Listener\r
+ *tx_fh = open(dmi_res->vtpm_tx_fname, O_WRONLY);\r
+ }\r
+ \r
+ if (*tx_fh < 0) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open outbound fh.\n");\r
+#ifdef VTPM_MULTI_VM\r
+ return TPM_IOERROR; \r
+#else\r
+ *ret_value = TPM_IOERROR;\r
+ pthread_exit(ret_value);\r
+#endif\r
+ } \r
+ \r
+ abort_with_error:\r
+ // Prepend VTPM header with destination DM stamped\r
+ out_param_size = buffer_len(result_buf);\r
+ out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size;\r
+ out_message_size_full = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size;\r
+ out_message = (BYTE *) malloc (out_message_size_full);\r
+ \r
+ BSG_PackList(out_message, 4,\r
+ BSG_TYPE_UINT32, (BYTE *) &dmi,\r
+ BSG_TPM_TAG, (BYTE *) &tag,\r
+ BSG_TYPE_UINT32, (BYTE *) &out_message_size,\r
+ BSG_TPM_RESULT, (BYTE *) &status);\r
+ \r
+ if (buffer_len(result_buf) > 0) \r
+ memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size);\r
+ \r
+ \r
+ //Note: Send message + dmi_id\r
+ size_write = write(*tx_fh, out_message, out_message_size_full );\r
+ if (size_write > 0) {\r
+ vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x");\r
+ for (i=0; i < out_message_size_full; i++) \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", out_message[i]);\r
+ \r
+ vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); \r
+ } else {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Error writing to BE. Aborting... \n");\r
+ close(*tx_fh);\r
+ *tx_fh = -1;\r
+ goto abort_command;\r
+ }\r
+ free(out_message);\r
+ \r
+ if (size_write < (int)out_message_size_full) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "Unable to write full command to BE (%d/%d)\n", size_write, out_message_size_full);\r
+ goto abort_command;\r
+ }\r
+ \r
+ abort_command:\r
+ //free buffers\r
+ bzero(cmd_header, VTPM_COMMAND_HEADER_SIZE_SRV);\r
+ //free(in_param); // This was converted to command_buf. No need to free \r
+ if (command_buf != result_buf) \r
+ buffer_free(result_buf);\r
+ \r
+ buffer_free(command_buf);\r
+ \r
+#ifndef VTPM_MULTI_VM\r
+ if (threadType != BE_LISTENER_THREAD) {\r
+#endif\r
+ if ( (vtpm_globals->DMI_table_dirty) &&\r
+ (VTPM_SaveService() != TPM_SUCCESS) ) {\r
+ vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager data.\n");\r
+ }\r
+#ifndef VTPM_MULTI_VM\r
+ }\r
+#endif\r
+ \r
+ } // End while(1)\r
+ \r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+TPM_RESULT VTPM_Init_Service() {\r
+ TPM_RESULT status = TPM_FAIL; \r
+ BYTE *randomsead;\r
+ UINT32 randomsize;\r
+ \r
+ if ((vtpm_globals = (VTPM_GLOBALS *) malloc(sizeof(VTPM_GLOBALS))) == NULL){\r
+ status = TPM_FAIL;\r
+ goto abort_egress;\r
+ }\r
+ memset(vtpm_globals, 0, sizeof(VTPM_GLOBALS));\r
+ vtpm_globals->be_fh = -1;\r
+\r
+#ifndef VTPM_MULTI_VM\r
+ vtpm_globals->vtpm_rx_fh = -1;\r
+ vtpm_globals->guest_rx_fh = -1;\r
+#endif\r
+ if ((vtpm_globals->dmi_map = create_hashtable(10, hashfunc32, equals32)) == NULL){\r
+ status = TPM_FAIL;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ vtpm_globals->DMI_table_dirty = FALSE;\r
+ \r
+ // Create new TCS Object\r
+ vtpm_globals->manager_tcs_handle = 0;\r
+ \r
+ TPMTRYRETURN(TCS_create());\r
+ \r
+ // Create TCS Context for service\r
+ TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) );\r
+\r
+ TPMTRYRETURN( TCSP_GetRandom(vtpm_globals->manager_tcs_handle, \r
+ &randomsize, \r
+ &randomsead));\r
+\r
+ Crypto_Init(randomsead, randomsize);\r
+ TPMTRYRETURN( TCS_FreeMemory (vtpm_globals->manager_tcs_handle, randomsead)); \r
+ \r
+ // Create OIAP session for service's authorized commands\r
+ TPMTRYRETURN( VTSP_OIAP( vtpm_globals->manager_tcs_handle, \r
+ &vtpm_globals->keyAuth) );\r
+ vtpm_globals->keyAuth.fContinueAuthSession = TRUE;\r
+\r
+ // If failed, create new Service.\r
+ if (VTPM_LoadService() != TPM_SUCCESS)\r
+ TPMTRYRETURN( VTPM_Create_Service() ); \r
+\r
+ \r
+ //Load Storage Key \r
+ TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,\r
+ TPM_SRK_KEYHANDLE,\r
+ &vtpm_globals->storageKeyWrap,\r
+ (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,\r
+ &vtpm_globals->storageKeyHandle,\r
+ &vtpm_globals->keyAuth,\r
+ &vtpm_globals->storageKey) );\r
+ \r
+ // Create entry for Dom0 for control messages\r
+ TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );\r
+ \r
+ // --------------------- Command handlers ---------------------------\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ egress:\r
+ \r
+ return(status);\r
+}\r
+ \r
+void VTPM_Stop_Service() {\r
+ VTPM_DMI_RESOURCE *dmi_res;\r
+ struct hashtable_itr *dmi_itr;\r
+ \r
+ // Close all the TCS contexts. TCS should evict keys based on this\r
+ if (hashtable_count(vtpm_globals->dmi_map) > 0) {\r
+ dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);\r
+ do {\r
+ dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);\r
+ if (dmi_res->connected) \r
+ if (close_dmi( dmi_res ) != TPM_SUCCESS) \r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to close dmi %d properly.\n", dmi_res->dmi_id);\r
+ \r
+ } while (hashtable_iterator_advance(dmi_itr));\r
+ free (dmi_itr);\r
+ }\r
+ \r
+ \r
+ TCS_CloseContext(vtpm_globals->manager_tcs_handle);\r
+ \r
+ if ( (vtpm_globals->DMI_table_dirty) &&\r
+ (VTPM_SaveService() != TPM_SUCCESS) )\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");\r
+ \r
+ hashtable_destroy(vtpm_globals->dmi_map, 1);\r
+ free(vtpm_globals);\r
+ \r
+ close(vtpm_globals->be_fh);\r
+ Crypto_Exit();\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n");\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtpm_manager.h\r
+// \r
+// Public Interface header for VTPM Manager\r
+//\r
+// ==================================================================\r
+\r
+#ifndef __VTPM_MANAGER_H__\r
+#define __VTPM_MANAGER_H__\r
+\r
+#include "tcg.h"\r
+\r
+#define VTPM_TAG_REQ 0x01c1\r
+#define VTPM_TAG_RSP 0x01c4\r
+#define COMMAND_BUFFER_SIZE 4096\r
+\r
+// Header sizes. Note Header MAY include the DMI\r
+#define VTPM_COMMAND_HEADER_SIZE_SRV ( sizeof(UINT32) + sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))\r
+#define VTPM_COMMAND_HEADER_SIZE_CLT ( sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE))\r
+\r
+// ********************** Public Functions *************************\r
+TPM_RESULT VTPM_Init_Service(); // Start VTPM Service\r
+void VTPM_Stop_Service(); // Stop VTPM Service\r
+#ifdef VTPM_MULTI_VM\r
+int VTPM_Service_Handler();\r
+#else\r
+void *VTPM_Service_Handler(void *threadTypePtr);\r
+#endif\r
+\r
+//************************ Command Codes ****************************\r
+#define VTPM_ORD_OPEN 1 // ULM Creates New DMI\r
+#define VTPM_ORD_CLOSE 2 // ULM Closes a DMI\r
+#define VTPM_ORD_DELETE 3 // ULM Permemently Deletes DMI\r
+#define VTPM_ORD_SAVENVM 4 // DMI requests Secrets Unseal\r
+#define VTPM_ORD_LOADNVM 5 // DMI requests Secrets Saved\r
+#define VTPM_ORD_TPMCOMMAND 6 // DMI issues HW TPM Command\r
+\r
+//************************ Return Codes ****************************\r
+#define VTPM_SUCCESS 0\r
+#define VTPM_FAIL 1\r
+#define VTPM_UNSUPPORTED 2\r
+#define VTPM_FORBIDDEN 3\r
+#define VTPM_RESTORE_CONTEXT_FAILED 4\r
+#define VTPM_INVALID_REQUEST 5\r
+\r
+/******************* Command Parameter API *************************\r
+\r
+VTPM Command Format\r
+ dmi: 4 bytes // Source of message. \r
+ // WARNING: This is prepended by the channel. \r
+ // Thus it is received by VTPM Manager, \r
+ // but not sent by DMI\r
+ tpm tag: 2 bytes\r
+ command size: 4 bytes // Size of command including header but not DMI\r
+ ord: 4 bytes // Command ordinal above\r
+ parameters: size - 10 bytes // Command Parameter\r
+\r
+VTPM Response Format\r
+ tpm tag: 2 bytes\r
+ response_size: 4 bytes\r
+ status: 4 bytes \r
+ parameters: size - 10 bytes\r
+\r
+\r
+VTPM_Open:\r
+ Input Parameters:\r
+ Domain_type: 1 byte\r
+ domain_id: 4 bytes\r
+ instance_id: 4 bytes\r
+ Output Parameters:\r
+ None\r
+ \r
+VTPM_Close\r
+ Input Parameters:\r
+ instance_id: 4 bytes\r
+ Output Parameters:\r
+ None\r
+\r
+VTPM_Delete\r
+ Input Parameters:\r
+ instance_id: 4 bytes\r
+ Output Parameters:\r
+ None\r
+\r
+VTPM_SaveNVM\r
+ Input Parameters:\r
+ data: n bytes (Header indicates size of data)\r
+ Output Parameters:\r
+ None\r
+\r
+VTPM_LoadNVM\r
+ Input Parameters:\r
+ None\r
+ Output Parameters:\r
+ data: n bytes (Header indicates size of data)\r
+\r
+VTPM_TPMCommand\r
+ Input Parameters:\r
+ TPM Command Byte Stream: n bytes \r
+ Output Parameters:\r
+ TPM Reponse Byte Stream: n bytes \r
+\r
+*********************************************************************/\r
+\r
+#endif //_VTPM_MANAGER_H_\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtpmd.c\r
+// \r
+// Application\r
+//\r
+// ===================================================================\r
+\r
+#include <stdio.h>\r
+#include <signal.h>\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+#include "vtpm_manager.h"\r
+#include "vtpmpriv.h"\r
+#include "tcg.h"\r
+#include "log.h"\r
+\r
+#ifndef VTPM_MULTI_VM\r
+ #include <pthread.h>\r
+#endif\r
+\r
+void signal_handler(int reason) {\r
+#ifndef VTPM_MULTI_VM\r
+\r
+ if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) {\r
+ if (reason >= 0) { // Reason is a signal\r
+ vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal %d.\n", reason);\r
+ } else {// Reason is a TPM_RESULT * -1\r
+ vtpmloginfo(VTPM_LOG_VTPM,"VTPM Manager shuting down for: %s\n", tpm_get_error_name(-1 * reason) );\r
+ }\r
+ \r
+ return;\r
+ } else {\r
+ vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n");\r
+ pthread_exit(NULL);\r
+ }\r
+#else\r
+ VTPM_Stop_Service();\r
+ exit(-1);\r
+#endif\r
+}\r
+\r
+struct sigaction ctl_c_handler;\r
+\r
+int main(int argc, char **argv) {\r
+\r
+ vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n");\r
+ \r
+ if (VTPM_Init_Service() != TPM_SUCCESS) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during startup.\n");\r
+ return -1;\r
+ }\r
+ \r
+ ctl_c_handler.sa_handler = signal_handler;\r
+ sigemptyset(&ctl_c_handler.sa_mask);\r
+ ctl_c_handler.sa_flags = 0; \r
+ \r
+ if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1) \r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+break will not stop service gently.\n");\r
+ \r
+ // For easier debuggin with gdb\r
+ if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1) \r
+ vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+break will not stop service gently.\n"); \r
+ \r
+#ifdef VTPM_MULTI_VM\r
+ TPM_RESULT status = VTPM_Service_Handler();\r
+ \r
+ if (status != TPM_SUCCESS) \r
+ vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager exited with status %s. It never should exit.\n", tpm_get_error_name(status));\r
+ \r
+ return -1;\r
+#else\r
+ sigset_t sig_mask;\r
+ \r
+ sigemptyset(&sig_mask);\r
+ sigaddset(&sig_mask, SIGPIPE);\r
+ sigprocmask(SIG_BLOCK, &sig_mask, NULL);\r
+ //pthread_mutex_init(&vtpm_globals->dmi_mutex, NULL);\r
+ pthread_t be_thread, dmi_thread;\r
+ int betype_be, dmitype_dmi;\r
+ \r
+ vtpm_globals->master_pid = pthread_self();\r
+ \r
+ betype_be = BE_LISTENER_THREAD;\r
+ if (pthread_create(&be_thread, NULL, VTPM_Service_Handler, &betype_be) != 0) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n");\r
+ exit(-1);\r
+ }\r
+ \r
+ dmitype_dmi = DMI_LISTENER_THREAD;\r
+ if (pthread_create(&dmi_thread, NULL, VTPM_Service_Handler, &dmitype_dmi) != 0) {\r
+ vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n");\r
+ exit(-1);\r
+ }\r
+ \r
+ //Join the other threads until exit time.\r
+ pthread_join(be_thread, NULL);\r
+ pthread_join(dmi_thread, NULL);\r
+ \r
+ VTPM_Stop_Service();\r
+ return 0;\r
+#endif\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtpmpriv.h\r
+// \r
+// Structures and functions private to the manager\r
+//\r
+// ==================================================================\r
+\r
+#ifndef __VTPMPRIV_H__\r
+#define __VTPMPRIV_H__\r
+\r
+#include "tcg.h"\r
+#include "tcs.h"\r
+#include "buffer.h"\r
+#include "crypto.h"\r
+\r
+#define STATE_FILE "/var/vtpm/VTPM"\r
+#define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data"\r
+#define VTPM_BE_DEV "/dev/vtpm"\r
+#define VTPM_CTL_DM 0\r
+\r
+#ifndef VTPM_MUTLI_VM\r
+ #include <sys/types.h>\r
+ #define GUEST_TX_FIFO "/var/vtpm/fifos/guest-to-%d.fifo"\r
+ #define GUEST_RX_FIFO "/var/vtpm/fifos/guest-from-all.fifo"\r
+\r
+ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm-to-%d.fifo"\r
+ #define VTPM_RX_FIFO "/var/vtpm/fifos/vtpm-from-all.fifo"\r
+\r
+ #define BE_LISTENER_THREAD 1\r
+ #define DMI_LISTENER_THREAD 2\r
+\r
+ // Seconds until DMI timeout. Timeouts result in DMI being out\r
+ // of sync, which may require a reboot of DMI and guest to recover\r
+ // from. Don't set this to low. Also note that DMI may issue a TPM\r
+ // call so we should expect time to process at DMI + TPM processing.\r
+ #define DMI_TIMEOUT 90 \r
+#endif\r
+\r
+\r
+// ------------------------ Private Structures -----------------------\r
+typedef struct VTPM_DMI_RESOURCE_T {\r
+ // I/O info for Manager to talk to DMI's over FIFOs\r
+#ifndef VTPM_MUTLI_VM\r
+ int guest_tx_fh; // open GUEST_TX_FIFO\r
+ int vtpm_tx_fh; // open VTPM_TX_FIFO\r
+ char *guest_tx_fname; // open GUEST_TX_FIFO\r
+ char *vtpm_tx_fname; // open VTPM_TX_FIFO\r
+ \r
+ pid_t dmi_pid;\r
+#endif\r
+ // Non-persistent Information\r
+ bool connected;\r
+ UINT32 dmi_domain_id;\r
+ TCS_CONTEXT_HANDLE TCSContext; // TCS Handle\r
+ char *NVMLocation; // NULL term string indicating location\r
+ // of NVM.\r
+ // Persistent Information about DMI\r
+ UINT32 dmi_id;\r
+ TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob\r
+ TPM_DIGEST DMI_measurement; // Correct measurement of the owning DMI\r
+} VTPM_DMI_RESOURCE;\r
+\r
+typedef struct tdVTPM_GLOBALS {\r
+ // Non-persistent data\r
+ int be_fh; // File handle to ipc used to communicate with backend\r
+#ifndef VTPM_MULTI_VM\r
+ int vtpm_rx_fh;\r
+ int guest_rx_fh;\r
+ \r
+ pid_t master_pid;\r
+#endif\r
+ struct hashtable *dmi_map; // Table of all DMI's known indexed by persistent instance #\r
+#ifndef VTPM_MULTI_VM\r
+ pthread_mutex_t dmi_map_mutex; // \r
+#endif\r
+ TCS_CONTEXT_HANDLE manager_tcs_handle; // TCS Handle used by manager\r
+ TPM_HANDLE storageKeyHandle; // Key used by persistent store\r
+ CRYPTO_INFO storageKey; // For software encryption\r
+ TCS_AUTH keyAuth; // OIAP session for storageKey \r
+ BOOL DMI_table_dirty; // Indicates that a command\r
+ // has updated the DMI table\r
+\r
+ \r
+ // Persistent Data\r
+ TPM_AUTHDATA owner_usage_auth; // OwnerAuth of real TPM\r
+ TPM_AUTHDATA srk_usage_auth; // SRK Auth of real TPM \r
+ buffer_t storageKeyWrap; // Wrapped copy of storageKey\r
+\r
+ TPM_AUTHDATA storage_key_usage_auth; \r
+ \r
+}VTPM_GLOBALS;\r
+\r
+//Global dmi map\r
+extern VTPM_GLOBALS *vtpm_globals;\r
+\r
+// ********************** Command Handler Prototypes ***********************\r
+TPM_RESULT VTPM_Handle_Load_NVM( VTPM_DMI_RESOURCE *myDMI, \r
+ const buffer_t *inbuf, \r
+ buffer_t *outbuf);\r
+\r
+TPM_RESULT VTPM_Handle_Save_NVM( VTPM_DMI_RESOURCE *myDMI, \r
+ const buffer_t *inbuf, \r
+ buffer_t *outbuf);\r
+\r
+TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi, \r
+ buffer_t *inbuf, \r
+ buffer_t *outbuf);\r
+\r
+TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf);\r
+ \r
+TPM_RESULT VTPM_Handle_Close_DMI(const buffer_t *param_buf);\r
+ \r
+TPM_RESULT VTPM_Handle_Delete_DMI(const buffer_t *param_buf);\r
+\r
+TPM_RESULT VTPM_SaveService(void);\r
+TPM_RESULT VTPM_LoadService(void);\r
+\r
+TPM_RESULT close_dmi( VTPM_DMI_RESOURCE *dmi_res);\r
+#endif // __VTPMPRIV_H__\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtsp.c\r
+// \r
+// Higher level interface to TCS for use in service.\r
+//\r
+// ==================================================================\r
+\r
+#include <string.h>\r
+#include "tcg.h"\r
+#include "tcs.h"\r
+#include "bsg.h"\r
+#include "log.h"\r
+#include "crypto.h"\r
+#include "vtsp.h"\r
+#include "buffer.h"\r
+\r
+#define RSA_KEY_SIZE 0x0800\r
+\r
+/***********************************************************************************\r
+ * GenerateAuth: Generate authorization info to be sent back to application\r
+ *\r
+ * Parameters: outParamDigestText The concatenation of output parameters to be SHA1ed\r
+ * outParamDigestTextSize Size of inParamDigestText\r
+ * HMACkey Key to be used for HMACing\r
+ * For OIAP use key.authUsage or PersistStore.ownerAuth\r
+ * For OSAP use shared secret\r
+ * pAuth Authorization information from the application\r
+ *\r
+ * Return: TPM_SUCCESS Authorization data created\r
+ * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP\r
+ *************************************************************************************/\r
+TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,\r
+ /*[IN]*/ UINT32 inParamDigestTextSize,\r
+ /*[IN]*/ const TPM_SECRET *HMACkey, \r
+ /*[IN,OUT]*/ TCS_AUTH *auth) {\r
+ \r
+ if (inParamDigestText == NULL || auth == NULL) \r
+ return (TPM_AUTHFAIL);\r
+ else {\r
+ \r
+ //Generate new OddNonce\r
+ Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));\r
+ \r
+ // Create SHA1 inParamDigest\r
+ TPM_DIGEST inParamDigest;\r
+ Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) &inParamDigest);\r
+ \r
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).\r
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];\r
+ \r
+ BSG_PackList( hmacText, 4, \r
+ BSG_TPM_DIGEST, &inParamDigest,\r
+ BSG_TPM_NONCE, &(auth->NonceEven),\r
+ BSG_TPM_NONCE, &(auth->NonceOdd), \r
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );\r
+ \r
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));\r
+ \r
+ return(TPM_SUCCESS);\r
+ \r
+ }\r
+}\r
+\r
+/***********************************************************************************\r
+ * VerifyAuth: Verify the authdata for a command requiring authorization\r
+ *\r
+ * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed\r
+ * inParamDigestTextSize Size of inParamDigestText\r
+ * authDataUsage AuthDataUsage for the Entity being used\r
+ * Key->authDataUsage or TPM_AUTH_OWNER\r
+ * HMACkey Key to be used for HMACing\r
+ * For OIAP use key.authUsage or PersistStore.ownerAuth\r
+ * For OSAP use NULL (It will be aquired from the Auth Session)\r
+ * If unknown (default), assume OIAP\r
+ * sessionAuth A TCS_AUTH info for the session\r
+ * pAuth Authorization information from the application\r
+ * hContext If specified, on failed Auth, VerifyAuth will\r
+ * generate a new OIAP session in place of themselves\r
+ * destroyed session.\r
+ *\r
+ * Return: TPM_SUCCESS Authorization Verified\r
+ * TPM_AUTHFAIL Authorization Failed\r
+ * TPM_FAIL Failure during SHA1 routines\r
+ *************************************************************************************/\r
+TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,\r
+ /*[IN]*/ UINT32 outParamDigestTextSize,\r
+ /*[IN]*/ const TPM_SECRET *HMACkey, \r
+ /*[IN,OUT]*/ TCS_AUTH *auth,\r
+ /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {\r
+ if (outParamDigestText == NULL || auth == NULL) \r
+ return (TPM_AUTHFAIL);\r
+ \r
+ \r
+ // Create SHA1 inParamDigest\r
+ TPM_DIGEST outParamDigest;\r
+ Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) &outParamDigest);\r
+ \r
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).\r
+ TPM_DIGEST hm;\r
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];\r
+ \r
+ BSG_PackList( hmacText, 4, \r
+ BSG_TPM_DIGEST, &outParamDigest,\r
+ BSG_TPM_NONCE, &(auth->NonceEven),\r
+ BSG_TPM_NONCE, &(auth->NonceOdd), \r
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );\r
+ \r
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),\r
+ (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);\r
+ \r
+ // Compare correct HMAC with provided one.\r
+ if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates equality\r
+ return (TPM_SUCCESS);\r
+ else {\r
+ VTSP_OIAP( hContext, auth);\r
+ return (TPM_AUTHFAIL);\r
+ }\r
+}\r
+\r
+TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,\r
+ TCS_AUTH *auth) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");\r
+ TPM_RESULT status = TPM_SUCCESS; \r
+ TPMTRYRETURN( TCSP_OIAP(hContext,\r
+ &auth->AuthHandle,\r
+ &auth->NonceEven) );\r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_ENTITY_TYPE entityType,\r
+ const UINT32 entityValue,\r
+ const TPM_AUTHDATA *usageAuth,\r
+ TPM_SECRET *sharedSecret, \r
+ TCS_AUTH *auth) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");\r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_NONCE nonceEvenOSAP, nonceOddOSAP;\r
+ \r
+ Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) ); \r
+ \r
+ TPMTRYRETURN( TCSP_OSAP( hContext,\r
+ TPM_ET_SRK,\r
+ 0, \r
+ nonceOddOSAP,\r
+ &auth->AuthHandle, \r
+ &auth->NonceEven, \r
+ &nonceEvenOSAP) );\r
+ \r
+ // Calculating Session Secret\r
+ BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];\r
+ \r
+ BSG_PackList( sharedSecretText, 2,\r
+ BSG_TPM_NONCE, &nonceEvenOSAP,\r
+ BSG_TPM_NONCE, &nonceOddOSAP);\r
+ \r
+ Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret); \r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ return status;\r
+}\r
+\r
+\r
+\r
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,\r
+ CRYPTO_INFO *crypto_info) {\r
+ \r
+ TPM_RESULT status;\r
+ TPM_NONCE antiReplay;\r
+ TPM_DIGEST checksum;\r
+ BYTE *pubEKtext;\r
+ UINT32 pubEKtextsize;\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");\r
+ \r
+ // GenerateAuth new nonceOdd \r
+ Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );\r
+ \r
+ \r
+ TPMTRYRETURN( TCSP_ReadPubek( hContext,\r
+ antiReplay,\r
+ &pubEKtextsize,\r
+ &pubEKtext,\r
+ &checksum) );\r
+ \r
+ \r
+ // Extract the remaining output parameters\r
+ TPM_PUBKEY pubEK;\r
+ \r
+ BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);\r
+ \r
+ // Build CryptoInfo for the bindingKey\r
+ TPM_RSA_KEY_PARMS rsaKeyParms;\r
+ \r
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, \r
+ pubEK.algorithmParms.parms, \r
+ &rsaKeyParms);\r
+ \r
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, \r
+ rsaKeyParms.exponent, \r
+ pubEK.pubKey.keyLength, \r
+ pubEK.pubKey.key, \r
+ crypto_info);\r
+ \r
+ // Destroy rsaKeyParms\r
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);\r
+\r
+ // Set encryption scheme\r
+ crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;\r
+ //crypto_info->encScheme = pubEK.algorithmParms.encScheme;\r
+ crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_AUTHDATA *ownerAuth, \r
+ const TPM_AUTHDATA *srkAuth,\r
+ CRYPTO_INFO *ek_cryptoInfo,\r
+ TCS_AUTH *auth) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;\r
+ TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;\r
+ BYTE *new_srk;\r
+ \r
+ BYTE *paramText; // Digest to make Auth.\r
+ UINT32 paramTextSize;\r
+ \r
+ // vars for srkpubkey parameter\r
+ TPM_KEY srkPub;\r
+ TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_SS_NONE, 12, 0};\r
+ BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};\r
+ srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;\r
+ \r
+ struct pack_buf_t srkText;\r
+ \r
+ // GenerateAuth new nonceOdd \r
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
+ \r
+ //These values are accurate for an enc(AuthData).\r
+ struct pack_buf_t encOwnerAuth, encSrkAuth;\r
+ \r
+ encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);\r
+ encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);\r
+ \r
+ if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");\r
+ status = TPM_RESOURCES;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, &encOwnerAuth.size, encOwnerAuth.data);\r
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, &encSrkAuth.size, encSrkAuth.data);\r
+ \r
+ \r
+ // Build srk public key struct\r
+ srkPub.ver = TPM_STRUCT_VER_1_1;\r
+ srkPub.keyUsage = TPM_KEY_STORAGE;\r
+ srkPub.keyFlags = 0x00;\r
+ srkPub.authDataUsage = TPM_AUTH_ALWAYS;\r
+ memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));\r
+ srkPub.PCRInfoSize = 0;\r
+ srkPub.PCRInfo = 0;\r
+ srkPub.pubKey.keyLength= 0;\r
+ srkPub.encDataSize = 0;\r
+ \r
+ srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);\r
+ \r
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ \r
+ paramTextSize = BSG_PackList(paramText, 5,\r
+ BSG_TPM_COMMAND_CODE,&command,\r
+ BSG_TPM_PROTOCOL_ID, &proto_id,\r
+ BSG_TPM_SIZE32_DATA, &encOwnerAuth,\r
+ BSG_TPM_SIZE32_DATA, &encSrkAuth,\r
+ BSG_TPM_KEY, &srkPub);\r
+ \r
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );\r
+ \r
+ new_srk = srkText.data;\r
+ TPMTRYRETURN( TCSP_TakeOwnership ( hContext,\r
+ proto_id,\r
+ encOwnerAuth.size, \r
+ encOwnerAuth.data,\r
+ encSrkAuth.size,\r
+ encSrkAuth.data,\r
+ &srkText.size,\r
+ &new_srk, \r
+ auth ) );\r
+ \r
+ \r
+ paramTextSize = BSG_PackList(paramText, 2, \r
+ BSG_TPM_RESULT, &status,\r
+ BSG_TPM_COMMAND_CODE, &command);\r
+ memcpy(paramText + paramTextSize, new_srk, srkText.size);\r
+ paramTextSize += srkText.size;\r
+ \r
+ \r
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
+ ownerAuth, auth, \r
+ hContext) );\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ free(srkText.data);\r
+ free(encSrkAuth.data);\r
+ free(encOwnerAuth.data);\r
+ free(paramText);\r
+ \r
+ TCS_FreeMemory(hContext, new_srk);\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_AUTHDATA *ownerAuth, \r
+ TCS_AUTH *auth) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;\r
+ \r
+ BYTE *paramText; // Digest to make Auth.\r
+ UINT32 paramTextSize;\r
+ \r
+ // Generate HMAC \r
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
+ \r
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ \r
+ paramTextSize = BSG_PackList(paramText, 1,\r
+ BSG_TPM_COMMAND_CODE, &command);\r
+ \r
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
+ ownerAuth, auth) );\r
+ \r
+ // Call TCS\r
+ TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in\r
+ auth) );\r
+ \r
+ // Verify Auth\r
+ paramTextSize = BSG_PackList(paramText, 2,\r
+ BSG_TPM_RESULT, &status,\r
+ BSG_TPM_COMMAND_CODE, &command);\r
+ \r
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
+ ownerAuth, auth, \r
+ hContext) );\r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ egress:\r
+ free(paramText);\r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_KEY_USAGE usage,\r
+ const TPM_AUTHDATA *newKeyAuth,\r
+ const TCS_KEY_HANDLE parentHandle, \r
+ const TPM_AUTHDATA *osapSharedSecret,\r
+ buffer_t *pubKeyBuf,\r
+ TCS_AUTH *auth) {\r
+ \r
+ int i;\r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);\r
+ \r
+ // vars for Calculate encUsageAuth\r
+ BYTE *paramText; \r
+ UINT32 paramTextSize;\r
+ \r
+ // vars for Calculate encUsageAuth\r
+ BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];\r
+ TPM_DIGEST XORKey1;\r
+ UINT32 XORbufferSize;\r
+ TPM_SECRET encUsageAuth, encMigrationAuth;\r
+ \r
+ // vars for Flatten newKey prototype\r
+ BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH; \r
+ struct pack_buf_t newKeyText;\r
+ \r
+ // Fill in newKey\r
+ TPM_KEY newKey;\r
+ \r
+ BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};\r
+ newKey.algorithmParms.algorithmID = TPM_ALG_RSA;\r
+ newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;\r
+ newKey.algorithmParms.parmSize = 12;\r
+ \r
+ switch (usage) {\r
+ case TPM_KEY_SIGNING:\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");\r
+ newKey.keyUsage = TPM_KEY_SIGNING;\r
+ newKey.algorithmParms.encScheme = TPM_ES_NONE;\r
+ newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;\r
+ break;\r
+ case TPM_KEY_STORAGE:\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");\r
+ newKey.keyUsage = TPM_KEY_STORAGE;\r
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;\r
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;\r
+ break;\r
+ case TPM_KEY_BIND:\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");\r
+ newKey.keyUsage = TPM_KEY_BIND;\r
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;\r
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;\r
+ break;\r
+ default:\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ \r
+ newKey.ver = TPM_STRUCT_VER_1_1;\r
+ \r
+ newKey.keyFlags = 0;\r
+ newKey.authDataUsage = TPM_AUTH_ALWAYS;\r
+ newKey.pubKey.keyLength= 0;\r
+ newKey.encDataSize = 0;\r
+ newKey.encData = NULL;\r
+ \r
+ // FIXME: Support PCR bindings\r
+ newKey.PCRInfoSize = 0;\r
+ newKey.PCRInfo = NULL;\r
+ \r
+ // Calculate encUsageAuth \r
+ XORbufferSize = BSG_PackList( XORbuffer, 2, \r
+ BSG_TPM_SECRET, osapSharedSecret,\r
+ BSG_TPM_NONCE, &auth->NonceEven);\r
+ Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);\r
+ \r
+ // FIXME: No support for migratable keys.\r
+ for (i=0; i < TPM_DIGEST_SIZE; i++) \r
+ ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *) newKeyAuth)[i];\r
+ \r
+ // Flatten newKey prototype\r
+ flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);\r
+ newKeyText.data = flatKey;\r
+ newKeyText.size = flatKeySize;\r
+ \r
+ // GenerateAuth new nonceOdd \r
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
+ \r
+ // Generate HMAC\r
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ \r
+ paramTextSize = BSG_PackList(paramText, 3,\r
+ BSG_TPM_COMMAND_CODE, &command,\r
+ BSG_TPM_AUTHDATA, &encUsageAuth,\r
+ BSG_TPM_AUTHDATA, &encMigrationAuth);\r
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);\r
+ paramTextSize += newKeyText.size;\r
+ \r
+ \r
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
+ osapSharedSecret, auth) );\r
+ \r
+ // Call TCS\r
+ TPMTRYRETURN( TCSP_CreateWrapKey( hContext, \r
+ parentHandle,\r
+ encUsageAuth,\r
+ encMigrationAuth,\r
+ &newKeyText.size,\r
+ &newKeyText.data,\r
+ auth) );\r
+ \r
+ // Verify Auth\r
+ paramTextSize = BSG_PackList(paramText, 2,\r
+ BSG_TPM_RESULT, &status,\r
+ BSG_TPM_COMMAND_CODE, &command);\r
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);\r
+ paramTextSize += newKeyText.size;\r
+ \r
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
+ osapSharedSecret, auth, 0) );\r
+ \r
+ // Unpack/return key structure\r
+ TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );\r
+ TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) );\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ free(flatKey);\r
+ free(paramText);\r
+ TCS_FreeMemory(hContext, newKeyText.data);\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,\r
+ const TCS_KEY_HANDLE hUnwrappingKey,\r
+ const buffer_t *rgbWrappedKeyBlob,\r
+ const TPM_AUTHDATA *parentAuth,\r
+ TPM_HANDLE *newKeyHandle,\r
+ TCS_AUTH *auth,\r
+ CRYPTO_INFO *cryptoinfo /*= NULL*/) {\r
+ \r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE command = TPM_ORD_LoadKey;\r
+ \r
+ BYTE *paramText; // Digest to make Auth.\r
+ UINT32 paramTextSize;\r
+ \r
+ if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || \r
+ (newKeyHandle==NULL) || (auth==NULL)) {\r
+ status = TPM_BAD_PARAMETER;\r
+ goto abort_egress;\r
+ }\r
+ \r
+ // Generate Extra TCS Parameters\r
+ TPM_HANDLE phKeyHMAC;\r
+ \r
+ // Generate HMAC\r
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
+ \r
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ \r
+ paramTextSize = BSG_PackList(paramText, 1,\r
+ BSG_TPM_COMMAND_CODE, &command);\r
+ \r
+ memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));\r
+ paramTextSize += buffer_len(rgbWrappedKeyBlob);\r
+ \r
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
+ parentAuth, auth) );\r
+ \r
+ // Call TCS\r
+ TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,\r
+ hUnwrappingKey,\r
+ buffer_len(rgbWrappedKeyBlob),\r
+ rgbWrappedKeyBlob->bytes,\r
+ auth,\r
+ newKeyHandle,\r
+ &phKeyHMAC) );\r
+ \r
+ // Verify Auth\r
+ paramTextSize = BSG_PackList(paramText, 3,\r
+ BSG_TPM_RESULT, &status,\r
+ BSG_TPM_COMMAND_CODE, &command,\r
+ BSG_TPM_HANDLE, newKeyHandle);\r
+ \r
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
+ parentAuth, auth, \r
+ hContext) );\r
+ \r
+ // Unpack/return key structure\r
+ if (cryptoinfo != NULL) {\r
+ TPM_KEY newKey;\r
+ \r
+ BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);\r
+ TPM_RSA_KEY_PARMS rsaKeyParms;\r
+ \r
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, \r
+ newKey.algorithmParms.parms, \r
+ &rsaKeyParms);\r
+ \r
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, \r
+ rsaKeyParms.exponent, \r
+ newKey.pubKey.keyLength, \r
+ newKey.pubKey.key, \r
+ cryptoinfo);\r
+ \r
+ // Destroy rsaKeyParms\r
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);\r
+ \r
+ // Set encryption scheme\r
+ cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;\r
+ }\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ free(paramText);\r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_KEY_HANDLE key_handle,\r
+ const buffer_t *bound_data,\r
+ const TPM_AUTHDATA *usage_auth,\r
+ buffer_t *clear_data,\r
+ TCS_AUTH *auth) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n", buffer_len(bound_data));\r
+ \r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ TPM_COMMAND_CODE command = TPM_ORD_UnBind;\r
+ \r
+ BYTE *paramText; // Digest to make Auth.\r
+ UINT32 paramTextSize;\r
+ \r
+ // Generate Extra TCS Parameters\r
+ struct pack_buf_t clear_data32;\r
+ BYTE *clear_data_text;\r
+ UINT32 clear_data_size;\r
+ \r
+ // Generate HMAC \r
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
+ \r
+ struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};\r
+ \r
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ \r
+ paramTextSize = BSG_PackList(paramText, 2,\r
+ BSG_TPM_COMMAND_CODE, &command,\r
+ BSG_TPM_SIZE32_DATA, &bound_data32);\r
+ \r
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
+ usage_auth, auth) );\r
+ \r
+ // Call TCS\r
+ TPMTRYRETURN( TCSP_UnBind( hContext,\r
+ key_handle,\r
+ buffer_len(bound_data),\r
+ bound_data->bytes,\r
+ auth,\r
+ &clear_data_size,\r
+ &clear_data_text) );\r
+ \r
+ \r
+ // Verify Auth\r
+ clear_data32.size = clear_data_size;\r
+ clear_data32.data = clear_data_text;\r
+ paramTextSize = BSG_PackList(paramText, 3,\r
+ BSG_TPM_RESULT, &status,\r
+ BSG_TPM_COMMAND_CODE, &command,\r
+ BSG_TPM_SIZE32_DATA, &clear_data32);\r
+ \r
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
+ usage_auth, auth, \r
+ hContext) );\r
+ \r
+ // Unpack/return key structure\r
+ TPMTRYRETURN(buffer_init(clear_data, 0, 0));\r
+ TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_data_text) );\r
+ \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ \r
+ free(paramText);\r
+ TCS_FreeMemory(hContext, clear_data_text);\r
+ \r
+ return status;\r
+}\r
+\r
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo, \r
+ const buffer_t *inData, \r
+ buffer_t *outData) \r
+{\r
+ vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n", buffer_len(inData));\r
+ TPM_BOUND_DATA boundData;\r
+ UINT32 i;\r
+ \r
+ // Fill boundData's accessory information\r
+ boundData.ver = TPM_STRUCT_VER_1_1;\r
+ boundData.payload = TPM_PT_BIND;\r
+ boundData.payloadData = inData->bytes;\r
+ \r
+ // Pack boundData before encryption\r
+ BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) * \r
+ (sizeof(TPM_VERSION) +\r
+ sizeof(TPM_PAYLOAD_TYPE) +\r
+ buffer_len(inData)));\r
+ if (flatBoundData == NULL) {\r
+ return TPM_NOSPACE;\r
+ }\r
+ UINT32 flatBoundDataSize = 0;\r
+ flatBoundDataSize = BSG_PackList( flatBoundData, 2, \r
+ BSG_TPM_VERSION, &boundData.ver, \r
+ BSG_TYPE_BYTE, &boundData.payload);\r
+ \r
+ memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));\r
+ flatBoundDataSize += buffer_len(inData);\r
+ \r
+ BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is what will come out.\r
+ UINT32 out_tmp_size;\r
+ \r
+ // Encrypt flatBoundData\r
+ Crypto_RSAEnc( cryptoInfo, \r
+ flatBoundDataSize, \r
+ flatBoundData, \r
+ &out_tmp_size, \r
+ out_tmp);\r
+ \r
+ if (out_tmp_size > RSA_KEY_SIZE/8) {\r
+ // The result of RSAEnc should be a fixed size based on key size.\r
+ vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");\r
+ }\r
+ \r
+ buffer_init(outData, 0, NULL);\r
+ buffer_append_raw(outData, out_tmp_size, out_tmp);\r
+ \r
+ vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);\r
+ for(i = 0 ; i < out_tmp_size ; i++) {\r
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);\r
+ }\r
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");\r
+ \r
+ // Free flatBoundData\r
+ free(flatBoundData);\r
+ \r
+ return TPM_SUCCESS;\r
+}\r
+\r
+// Function Reaches into unsupported TCS command, beware.\r
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,\r
+ const buffer_t *inbuf,\r
+ buffer_t *outbuf ) {\r
+ \r
+ vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");\r
+ TPM_RESULT status = TPM_SUCCESS;\r
+ \r
+ // Generate Extra TCS Parameters\r
+ BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
+ UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;\r
+ \r
+ // Call TCS \r
+ TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes, \r
+ &resultTextSize, resultText) );\r
+ \r
+ // Unpack/return key structure\r
+ TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) ); \r
+ goto egress;\r
+ \r
+ abort_egress:\r
+ \r
+ egress:\r
+ TCS_FreeMemory(hContext, resultText);\r
+ free(resultText);\r
+ return status;\r
+}\r
--- /dev/null
+// ===================================================================\r
+// \r
+// Copyright (c) 2005, Intel Corp.\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without \r
+// modification, are permitted provided that the following conditions \r
+// are met:\r
+//\r
+// * Redistributions of source code must retain the above copyright \r
+// notice, this list of conditions and the following disclaimer.\r
+// * Redistributions in binary form must reproduce the above \r
+// copyright notice, this list of conditions and the following \r
+// disclaimer in the documentation and/or other materials provided \r
+// with the distribution.\r
+// * Neither the name of Intel Corporation nor the names of its \r
+// contributors may be used to endorse or promote products derived\r
+// from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
+// OF THE POSSIBILITY OF SUCH DAMAGE.\r
+// ===================================================================\r
+// \r
+// vtsp.h\r
+// \r
+// Higher level interface to TCS.\r
+//\r
+// ==================================================================\r
+\r
+#ifndef __VTSP_H__\r
+#define __VTSP_H__\r
+\r
+#include "tcg.h"\r
+#include "tcs.h"\r
+\r
+#define KEY_BUFFER_SIZE 2048\r
+\r
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,\r
+ const buffer_t *inbuf,\r
+ buffer_t *outbuf );\r
+\r
+TPM_RESULT VTSP_OIAP( const TCS_CONTEXT_HANDLE hContext,\r
+ TCS_AUTH *auth);\r
+ \r
+TPM_RESULT VTSP_OSAP( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_ENTITY_TYPE entityType,\r
+ const UINT32 entityValue,\r
+ const TPM_AUTHDATA *usageAuth,\r
+ TPM_SECRET *sharedsecret, \r
+ TCS_AUTH *auth);\r
+\r
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,\r
+ CRYPTO_INFO *cypto_info);\r
+\r
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_AUTHDATA *ownerAuth, \r
+ const TPM_AUTHDATA *srkAuth,\r
+ CRYPTO_INFO *ek_cryptoInfo,\r
+ TCS_AUTH *auth);\r
+ \r
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_AUTHDATA *ownerAuth, \r
+ TCS_AUTH *auth);\r
+ \r
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_KEY_USAGE usage,\r
+ const TPM_AUTHDATA *newKeyAuth,\r
+ const TCS_KEY_HANDLE parentHandle, \r
+ const TPM_AUTHDATA *osapSharedSecret,\r
+ buffer_t *pubKeyBuf,\r
+ TCS_AUTH *auth);\r
+\r
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,\r
+ const TCS_KEY_HANDLE hUnwrappingKey,\r
+ const buffer_t *rgbWrappedKeyBlob,\r
+ const TPM_AUTHDATA *parentAuth,\r
+ TPM_HANDLE *newKeyHandle,\r
+ TCS_AUTH *pAuth,\r
+ CRYPTO_INFO *cryptoinfo);\r
+\r
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,\r
+ const TPM_KEY_HANDLE key_handle,\r
+ const buffer_t *bound_data,\r
+ const TPM_AUTHDATA *usage_auth,\r
+ buffer_t *clear_data,\r
+ TCS_AUTH *auth);\r
+ \r
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,\r
+ const buffer_t *inData, \r
+ buffer_t *outData);\r
+ \r
+#endif //_VTSP_H_\r
--- /dev/null
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+
+BIN = libTCS.a
+
+all: build
+
+build: $(BIN)
+
+install: build
+
+clean:
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)
+
+mrproper: clean
+
+$(BIN): $(OBJS)
+ $(AR) rcs $(BIN) $(OBJS)
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "tcs.h"
+#include "contextmgr.h"
+#include "log.h"
+
+BYTE* AddMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize) { // in
+
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pBlock = NULL;
+
+ // check incoming params
+ if (pContextHandle == NULL || BlockSize == 0)
+ return NULL;
+
+ // Create New Block
+ pBlock = (BLOCK *)malloc(sizeof(BLOCK));
+ if (pBlock == NULL)
+ return (0);
+
+ pBlock->aMemory = (BYTE *)malloc(sizeof(BYTE) * BlockSize);
+ if (pBlock->aMemory == NULL)
+ return (0);
+
+ memset(pBlock->aMemory, 0, BlockSize);
+ pBlock->nBlockSize = BlockSize;
+ pBlock->pNextBlock = NULL;
+
+ // search for the last block created where to add the
+ // newly created block
+ if(pContextHandle->pTopBlock != NULL) {
+ pCurrentBlock = pContextHandle->pTopBlock;
+ while(pCurrentBlock->pNextBlock != NULL)
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+
+
+ pCurrentBlock->pNextBlock= pBlock;
+ } else
+ pContextHandle->pTopBlock = pBlock;
+
+
+ pContextHandle->nBlockCount++;
+
+ return pBlock->aMemory;
+}
+
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs) { // in
+ BLOCK* pCurrentBlock = NULL;
+ BLOCK* pParentBlock = NULL;
+ BOOL bFound = FALSE;
+
+ if (pContextHandle == NULL)
+ return FALSE;
+
+
+ // Search for the Block in the context by aMemory pointer
+ pParentBlock = NULL;
+ pCurrentBlock = pContextHandle->pTopBlock;
+
+ while(pCurrentBlock != NULL) {
+ // If aMemory block is found, delete it
+ if(pCurrentBlock->aMemory == pTCPA_BYTEs || pTCPA_BYTEs == NULL) {
+ // if it is the top Block, remove it from the top,
+ // otherwise remove it from the ParentBlock and stitch
+ // the NextBlock to the ParentBlock
+ if(pParentBlock == NULL)
+ pContextHandle->pTopBlock = pContextHandle->pTopBlock->pNextBlock;
+ else
+ pParentBlock->pNextBlock = pCurrentBlock->pNextBlock;
+
+ // delete memory Block associated with pointer pTCPA_BYTEs
+ free(pCurrentBlock->aMemory);
+ pCurrentBlock->aMemory = NULL;
+
+ free(pCurrentBlock);
+ pCurrentBlock = pParentBlock;
+
+ pContextHandle->nBlockCount--;
+ bFound = TRUE;
+ }
+
+ if(pCurrentBlock != NULL) {
+ pParentBlock = pCurrentBlock;
+ pCurrentBlock = pCurrentBlock->pNextBlock;
+ }
+ }
+
+ return bFound;
+}
+
+BOOL AddHandleToList(CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle) { // in
+ HANDLE_LIST* pNewHandle = NULL;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Adding Handle to list\n");
+ if (pContextHandle == NULL)
+ return 0;
+
+ pNewHandle = (HANDLE_LIST *)malloc(sizeof(HANDLE_LIST));
+
+ if (pNewHandle == NULL)
+ return (0);
+
+ pNewHandle->handle = handle;
+ pNewHandle->type = type;
+ pNewHandle->pNextHandle = pContextHandle->pHandleList;
+
+ pContextHandle->pHandleList = pNewHandle;
+
+ return 1;
+}
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle) { // in
+
+ HANDLE_LIST *pCurrentHandle = pContextHandle->pHandleList,
+ *pLastHandle = pCurrentHandle;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Deleting Handle from list\n");
+
+ if (pContextHandle == NULL)
+ return 0;
+
+ while (1) {
+
+ if (pCurrentHandle->handle == handle) { // Found element
+ if (pCurrentHandle == pLastHandle) { // First element in list
+ pContextHandle->pHandleList = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ } else { // Ordinary element
+ pLastHandle->pNextHandle = pCurrentHandle->pNextHandle;
+ free(pCurrentHandle);
+ }
+
+ return 1;
+
+ } else { // Not found yet;
+ pLastHandle = pCurrentHandle;
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+ if (pCurrentHandle == NULL) // Found end of list
+ return 0;
+ }
+
+ }
+}
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in
+ HANDLE_LIST* pCurrentHandle;
+ BOOL returncode = TRUE;
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n");
+
+ if (pContextHandle == NULL)
+ return 1;
+
+ pCurrentHandle = pContextHandle->pHandleList;
+ while (pCurrentHandle != NULL) {
+
+ switch (pCurrentHandle->type) {
+ case TPM_RT_KEY:
+ returncode = returncode && !TCSP_EvictKey((TCS_CONTEXT_HANDLE) pContextHandle, pCurrentHandle->handle);
+ break;
+ case TPM_RT_AUTH:
+ returncode = returncode && !TCSP_TerminateHandle((TCS_CONTEXT_HANDLE) pContextHandle, pCurrentHandle->handle);
+ break;
+ default:
+ returncode = FALSE;
+ }
+
+ pCurrentHandle = pCurrentHandle->pNextHandle;
+
+ }
+
+ return 1;
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// contextmgr.c
+//
+// This file contains the context management functions for TCS.
+//
+// ==================================================================
+
+#ifndef __CONTEXTMGR_H__
+#define __CONTEXTMGR_H__
+
+#include "tcg.h"
+
+#define BLOCK_SIZE 300
+
+typedef struct block {
+ int nBlockSize;
+ BYTE* aMemory;
+ struct block* pNextBlock;
+} BLOCK;
+
+typedef struct handle_List {
+ TPM_HANDLE handle;
+ TPM_RESOURCE_TYPE type;
+ struct handle_List* pNextHandle;
+} HANDLE_LIST;
+
+typedef struct context_handle {
+ int nBlockCount;
+ BLOCK* pTopBlock;
+ HANDLE_LIST* pHandleList;
+} CONTEXT_HANDLE;
+
+BYTE* AddMemBlock( CONTEXT_HANDLE* pContextHandle, // in
+ int BlockSize); // in
+
+BOOL DeleteMemBlock(CONTEXT_HANDLE* pContextHandle, // in
+ BYTE* pTCPA_BYTEs); // in
+
+
+BOOL AddHandleToList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_RESOURCE_TYPE type, // in
+ TPM_HANDLE handle); // in
+
+BOOL DeleteHandleFromList( CONTEXT_HANDLE* pContextHandle, // in
+ TPM_HANDLE handle); // in
+
+BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle); // in
+
+#endif //_CONTEXTMGR_H_
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcs.c
+//
+// This file contains the functions that implement a TCS.
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "tcs.h"
+#include "contextmgr.h"
+#include "tpmddl.h"
+#include "log.h"
+
+// Static Global Vars for the TCS
+static BOOL TCS_m_bConnected;
+static int TCS_m_nCount = 0;
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+static BYTE InBuf [TCPA_MAX_BUFFER_LENGTH];
+static BYTE OutBuf[TCPA_MAX_BUFFER_LENGTH];
+
+
+// ---------------------------------------------------------------------------------
+// Initialization/Uninitialization SubComponent API
+// ---------------------------------------------------------------------------------
+TPM_RESULT TCS_create() {
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TPM_RESULT result = TPM_FAIL;
+ TCS_m_bConnected = FALSE;
+
+ if (TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Constructing new TCS:\n");
+ hRes = TDDL_Open();
+
+ if (hRes == TDDL_SUCCESS) {
+ TCS_m_bConnected = TRUE;
+ result = TPM_SUCCESS;
+ }
+ } else
+ TCS_m_bConnected = TRUE;
+
+ TCS_m_nCount++;
+
+ return(result);
+}
+
+
+void TCS_destroy()
+{
+ // FIXME: Should iterate through all open contexts and close them.
+ TCS_m_nCount--;
+
+ if (TCS_m_bConnected == TRUE && TCS_m_nCount == 0) {
+ vtpmloginfo(VTPM_LOG_TCS, "Destructing TCS:\n");
+ TDDL_Close();
+ TCS_m_bConnected = FALSE;
+ }
+
+}
+
+TPM_RESULT TCS_Malloc( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr) {// out
+
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if (pContextHandle != NULL && ppMemPtr != NULL) {
+ *ppMemPtr = (BYTE *)AddMemBlock(pContextHandle, MemSize);
+ returnCode = TPM_SUCCESS;
+ }
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_FreeMemory( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory) { // in
+ TPM_RESULT returnCode = TPM_FAIL;
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if ( (pContextHandle != NULL && pMemory != NULL) &&
+ (DeleteMemBlock(pContextHandle, pMemory) == TRUE) )
+ returnCode = TPM_SUCCESS;
+
+
+ return returnCode;
+}
+
+TPM_RESULT TCS_OpenContext(TCS_CONTEXT_HANDLE* hContext) { // out
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_OpenContext:\n");
+
+ // hContext must point to a null memory context handle
+ if(*hContext == HANDLE_NULL) {
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE *)malloc(sizeof(CONTEXT_HANDLE));
+ if (pContextHandle == NULL)
+ return TPM_SIZE;
+
+
+ // initialize to 0
+ pContextHandle->nBlockCount = 0;
+ pContextHandle->pTopBlock = NULL;
+ pContextHandle->pHandleList = NULL;
+
+ // Create New Block
+ AddMemBlock(pContextHandle, BLOCK_SIZE);
+
+ *hContext = (TCS_CONTEXT_HANDLE)pContextHandle;
+ returnCode = TPM_SUCCESS;
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCS_CloseContext(TCS_CONTEXT_HANDLE hContext) {// in
+ //FIXME: TCS SHOULD Track track failed auths and make sure
+ //we don't try and re-free them here.
+ TPM_RESULT returnCode = TPM_FAIL;
+
+ CONTEXT_HANDLE* pContextHandle = (CONTEXT_HANDLE*)hContext;
+
+ if(pContextHandle != NULL) {
+ // Print test info
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TCS_CloseContext.\n");
+
+ // free memory for all the blocks
+ DeleteMemBlock(pContextHandle, NULL );
+ pContextHandle->pTopBlock = NULL;
+
+ FreeHandleList(pContextHandle);
+ if (pContextHandle->pHandleList != NULL)
+ vtpmlogerror(VTPM_LOG_TCS, "Not all handles evicted from TPM.\n");
+
+ // Release the TPM's resources
+ free(pContextHandle);
+ returnCode = TPM_SUCCESS;
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Finished closing context\n");
+ return(returnCode);
+}
+
+// ------------------------------------------------------------------
+// Internal Functions
+// ------------------------------------------------------------------
+int packAuth(BYTE* dst, TCS_AUTH* auth) {
+ // CHECK: according to the command specs, the outgoing auth params are:
+ // nonceEven
+ // nonceOdd
+ // continueAuthSession
+ // auth digest for return params
+ //
+ // this is a bit different than this code...
+
+ return BSG_PackList(dst, 4,
+ BSG_TYPE_UINT32, &(auth->AuthHandle),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+int unpackAuth(TCS_AUTH* auth, BYTE* src) {
+ return BSG_UnpackList(src, 3,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession),
+ BSG_TPM_AUTHDATA, &(auth->HMAC));
+}
+
+// ------------------------------------------------------------------
+// Authorization Commands
+// ------------------------------------------------------------------
+
+TPM_RESULT TCSP_OIAP(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OIAP;
+ UINT32 paramSize = 0;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonce0 == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 2,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonce0);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH, *authHandle))
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n", tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_OSAP(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_OSAP;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (authHandle == NULL || nonceEven == NULL || nonceEvenOSAP == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &entityType,
+ BSG_TYPE_UINT32, &entityValue,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_UnpackList(OutBuf+i, 3,
+ BSG_TYPE_UINT32, authHandle,
+ BSG_TPM_NONCE, nonceEven,
+ BSG_TPM_NONCE, nonceEvenOSAP);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_AUTH, *authHandle)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New AuthHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "Failed with return code %s\n", tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_TakeOwnership(TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_TakeOwnership;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (encOwnerAuth == NULL || encSrkAuth == NULL || SrkSize == NULL || *Srk == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT16, &protocolID,
+ BSG_TYPE_UINT32, &encOwnerAuthSize);
+
+ memcpy(InBuf+InLength, encOwnerAuth, encOwnerAuthSize);
+ InLength += encOwnerAuthSize;
+ InLength += BSG_Pack( BSG_TYPE_UINT32,
+ &encSrkAuthSize,
+ InBuf+InLength);
+ memcpy(InBuf+InLength, encSrkAuth, encSrkAuthSize);
+ InLength += encSrkAuthSize;
+ memcpy(InBuf+InLength, *Srk, *SrkSize);
+ InLength += *SrkSize;
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32,
+ &InLength,
+ InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY srkPub;
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &srkPub);
+ unpackAuth(ownerAuth, OutBuf+i);
+
+ // fill output params
+ BYTE tempBuf[1024];
+ *SrkSize = BSG_Pack(BSG_TPM_KEY, &srkPub, tempBuf);
+ if (TCS_Malloc(hContext, *SrkSize, Srk) == TPM_FAIL) {
+ return(TPM_SIZE);
+ }
+ memcpy(*Srk, tempBuf, *SrkSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TakeOwnership Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth) { // in, out
+
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_DisablePubekRead;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal);
+
+ InLength += packAuth(InBuf+InLength, ownerAuth);
+
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS){
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ unpackAuth(ownerAuth, OutBuf+i);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_DisablePubekRead Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Terminate_Handle;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &handle);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, handle))
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Print debug info
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_TerminateHandle Failed with return code %s\n", tpm_get_error_name(returnCode));
+
+ }
+
+ return(returnCode);
+}
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Extend;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &pcrNum,
+ BSG_TPM_DIGEST, &inDigest);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+
+ // unpack to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND){
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TPM_PCRVALUE, OutBuf+i, outDigest);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Extend Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Seal( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Seal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || *SealedData == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TPM_ENCAUTH, encAuth,
+ BSG_TYPE_UINT32, &pcrInfoSize);
+ memcpy(InBuf+InLength, PcrInfo, pcrInfoSize);
+ InLength += pcrInfoSize;
+ InLength += BSG_Pack(BSG_TYPE_UINT32, &inDataSize, InBuf+InLength);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, pubAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
+ == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_STORED_DATA sealedData;
+
+ i += BSG_Unpack(BSG_TPM_STORED_DATA, OutBuf+i, &sealedData);
+ unpackAuth(pubAuth, OutBuf+i);
+
+ // fill SealedData
+ BYTE tempBuf[1024];
+ *SealedDataSize = BSG_Pack(BSG_TPM_STORED_DATA, &sealedData, tempBuf);
+ if (TCS_Malloc(hContext, *SealedDataSize, SealedData) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*SealedData, tempBuf, *SealedDataSize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Seal Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_Unseal(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH2_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_Unseal;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (SealedData == NULL || parentAuth == NULL || dataAuth == NULL ||
+ DataSize == NULL || Data == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &parentHandle);
+ memcpy(InBuf+InLength, SealedData, SealedDataSize);
+ InLength += SealedDataSize;
+ InLength += packAuth(InBuf+InLength, parentAuth);
+ InLength += packAuth(InBuf+InLength, dataAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList( OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH2_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, DataSize);
+ if (TCS_Malloc(hContext, *DataSize, Data) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*Data, OutBuf+i, *DataSize);
+ i += *DataSize;
+ i += unpackAuth(parentAuth, OutBuf+i);
+ unpackAuth(dataAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_Unseal Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_UnBind(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_UnBind;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (inData == NULL || privAuth == NULL || outDataSize == NULL || *outData == NULL)
+ return TPM_BAD_PARAMETER;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 5,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &keyHandle,
+ BSG_TYPE_UINT32, &inDataSize);
+ memcpy(InBuf+InLength, inData, inDataSize);
+ InLength += inDataSize;
+ InLength += packAuth(InBuf+InLength, privAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "\n\tSending paramSize = %d", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, outDataSize);
+ if (TCS_Malloc(hContext, *outDataSize, outData) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*outData, OutBuf+i, *outDataSize);
+ i += *outDataSize;
+ unpackAuth(privAuth, OutBuf+i);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_UnBind Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth) // in, out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_CreateWrapKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pcKeySize == NULL || *prgbKey == NULL || pAuth == NULL)
+ return TPM_BAD_PARAMETER;
+
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 6,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hWrappingKey,
+ BSG_TPM_ENCAUTH, KeyUsageAuth,
+ BSG_TPM_ENCAUTH, KeyMigrationAuth);
+ memcpy(InBuf+InLength, *prgbKey, *pcKeySize);
+ InLength += *pcKeySize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_RESULT, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_KEY wrappedKey;
+
+ i += BSG_Unpack(BSG_TPM_KEY, OutBuf+i, &wrappedKey);
+ unpackAuth(pAuth, OutBuf+i);
+
+ // Fill prgbKey
+ BYTE tempBuf[1024];
+ *pcKeySize = BSG_Pack(BSG_TPM_KEY, &wrappedKey, tempBuf);
+ if (TCS_Malloc(hContext, *pcKeySize, prgbKey) == TPM_FAIL)
+ return TPM_SIZE;
+
+ memcpy(*prgbKey, tempBuf, *pcKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_LoadKeyByBlob(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_AUTH1_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_LoadKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (rgbWrappedKeyBlob == NULL || pAuth == NULL || phKeyTCSI == NULL || phKeyHMAC == NULL)
+ return TPM_BAD_PARAMETER;
+
+ *phKeyHMAC = hUnwrappingKey; // the parent key is the one that the TPM use to make the HMAC calc
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hUnwrappingKey);
+ memcpy(InBuf+InLength, rgbWrappedKeyBlob, cWrappedKeyBlobSize);
+ InLength += cWrappedKeyBlobSize;
+ InLength += packAuth(InBuf+InLength, pAuth);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_AUTH1_COMMAND) {
+ // Extract the remaining output parameters
+ i += BSG_Unpack(BSG_TYPE_UINT32,
+ OutBuf+i,
+ phKeyTCSI);
+ unpackAuth(pAuth, OutBuf+i);
+
+ if (!AddHandleToList((CONTEXT_HANDLE *)hContext, TPM_RT_KEY, *phKeyTCSI)) {
+ vtpmlogerror(VTPM_LOG_TCS, "New KeyHandle not recorded\n");
+ }
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_LoadKeyByBlob Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey) // in
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_EvictKey;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, &hKey);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (!DeleteHandleFromList((CONTEXT_HANDLE *)hContext, hKey)) {
+ vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+ }
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_EvictKey Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_GetRandom;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (bytesRequested == NULL || *randomBytes == NULL){
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TYPE_UINT32, bytesRequested);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ BSG_Unpack(BSG_TYPE_UINT32, OutBuf+i, bytesRequested);
+ if (TCS_Malloc(hContext, *bytesRequested, randomBytes) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*randomBytes, OutBuf+i+sizeof(UINT32), *bytesRequested);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_GetRandom Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+
+TPM_RESULT TCSP_ReadPubek(TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum) // out
+{
+ // setup input/output parameters block
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 paramSize = 0;
+ TPM_COMMAND_CODE ordinal = TPM_ORD_ReadPubek;
+ TPM_RESULT returnCode = TPM_SUCCESS;
+
+ // setup the TPM driver input and output buffers
+ TDDL_RESULT hRes = TDDL_E_FAIL;
+ TDDL_UINT32 InLength = TCPA_MAX_BUFFER_LENGTH;
+ TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
+
+ // check input params
+ if (pubEndorsementKeySize == NULL || pubEndorsementKey == NULL || checksum == NULL) {
+ return TPM_BAD_PARAMETER;
+ }
+
+ // Convert Byte Input parameter in the input byte stream InBuf
+ InLength = BSG_PackList(InBuf, 4,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &ordinal,
+ BSG_TPM_NONCE, &antiReplay);
+ // fill paramSize again as we now have the correct size
+ BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+ // call the TPM driver
+ if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) {
+ // unpack OutBuf to get the tag, paramSize, & returnCode
+ int i = BSG_UnpackList(OutBuf, 3,
+ BSG_TPM_TAG, &tag,
+ BSG_TYPE_UINT32, ¶mSize,
+ BSG_TPM_COMMAND_CODE, &returnCode);
+
+ if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+ i += BSG_UnpackList(OutBuf+i, 2,
+ BSG_TPM_PUBKEY, &pubEK,
+ BSG_TPM_DIGEST, checksum);
+
+ // fill EndorsementKey
+ BYTE tempBuf[1024];
+ *pubEndorsementKeySize = BSG_Pack(BSG_TPM_PUBKEY, &pubEK, tempBuf);
+ if (TCS_Malloc(hContext, *pubEndorsementKeySize, pubEndorsementKey) == TPM_FAIL) {
+ return TPM_SIZE;
+ }
+ memcpy(*pubEndorsementKey, tempBuf, *pubEndorsementKeySize);
+
+ vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize);
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_ReadPubek Failed with return code %s\n", tpm_get_error_name(returnCode));
+ }
+ }
+
+ return(returnCode);
+}
+
+TPM_RESULT TCSP_RawTransmitData( UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData) { // out
+
+ TDDL_RESULT hRes;
+
+ vtpmloginfo(VTPM_LOG_TCS, "Calling TransmitData directly.\n");
+ //FIXME: Add Context Management
+ hRes = TDDL_TransmitData( inData,
+ inDataSize,
+ outData,
+ outDataSize);
+
+ if (hRes == TDDL_SUCCESS) {
+ return TPM_SUCCESS;
+ } else {
+ vtpmlogerror(VTPM_LOG_TCS, "TCSP_RawTransmitData Failed with return code %s\n", tpm_get_error_name(TPM_IOERROR));
+ return TPM_IOERROR;
+ }
+
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcs.h
+//
+// This file declares the TCS API
+//
+// ==================================================================
+
+#ifndef __TCS_H__
+#define __TCS_H__
+
+#include "tcg.h"
+#include "buffer.h"
+
+#define HANDLE_NULL 0
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+TPM_RESULT TCS_create();
+void TCS_destroy();
+
+TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext );
+
+TPM_RESULT TCS_CloseContext ( /* IN */ TCS_CONTEXT_HANDLE hContext );
+
+TPM_RESULT TCS_Malloc ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 MemSize, // in
+ BYTE** ppMemPtr ); //out
+
+TPM_RESULT TCS_FreeMemory ( TCS_CONTEXT_HANDLE hContext, // in
+ BYTE* pMemory); // in
+
+// ------------------------------------------------------------------
+// Exposed API
+// ------------------------------------------------------------------
+
+// TPM v1.1B Command Set
+
+// Authorzation
+TPM_RESULT TCSP_OIAP( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonce0 // out
+ );
+
+TPM_RESULT TCSP_OSAP ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_ENTITY_TYPE entityType, // in
+ UINT32 entityValue, // in
+ TPM_NONCE nonceOddOSAP, // in
+ TCS_AUTHHANDLE* authHandle, // out
+ TPM_NONCE* nonceEven, // out
+ TPM_NONCE* nonceEvenOSAP // out
+ );
+
+TPM_RESULT TCSP_TakeOwnership ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT16 protocolID, // in
+ UINT32 encOwnerAuthSize, // in
+ BYTE* encOwnerAuth, // in
+ UINT32 encSrkAuthSize, // in
+ BYTE* encSrkAuth, // in
+ UINT32* SrkSize, // in, out
+ BYTE** Srk, // in, out
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DisablePubekRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_TerminateHandle ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle // in
+ );
+
+TPM_RESULT TCSP_FlushSpecific ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_AUTHHANDLE handle, // in
+ TPM_RESOURCE_TYPE resourceType //in
+ );
+
+// TPM Mandatory
+TPM_RESULT TCSP_Extend ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_DIGEST inDigest, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_PcrRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_PCRINDEX pcrNum, // in
+ TPM_PCRVALUE* outDigest // out
+ );
+
+TPM_RESULT TCSP_Quote ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* PcrDataSize, // in, out
+ BYTE** PcrData, // in, out
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_Seal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ TPM_ENCAUTH encAuth, // in
+ UINT32 pcrInfoSize, // in
+ BYTE* PcrInfo, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* pubAuth, // in, out
+ UINT32* SealedDataSize, // out
+ BYTE** SealedData // out
+ );
+
+TPM_RESULT TCSP_Unseal ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE parentHandle, // in
+ UINT32 SealedDataSize, // in
+ BYTE* SealedData, // in
+ TCS_AUTH* parentAuth, // in, out
+ TCS_AUTH* dataAuth, // in, out
+ UINT32* DataSize, // out
+ BYTE** Data // out
+ );
+
+TPM_RESULT TCSP_DirWriteAuth ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE newContents, // in
+ TCS_AUTH* ownerAuth // in, out
+ );
+
+TPM_RESULT TCSP_DirRead ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_DIRINDEX dirIndex, // in
+ TPM_DIRVALUE* dirValue // out
+ );
+
+TPM_RESULT TCSP_UnBind ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 inDataSize, // in
+ BYTE* inData, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* outDataSize, // out
+ BYTE** outData // out
+ );
+
+TPM_RESULT TCSP_CreateWrapKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hWrappingKey, // in
+ TPM_ENCAUTH KeyUsageAuth, // in
+ TPM_ENCAUTH KeyMigrationAuth, // in
+ UINT32* pcKeySize, // in, out
+ BYTE** prgbKey, // in, out
+ TCS_AUTH* pAuth // in, out
+ );
+
+TPM_RESULT TCSP_LoadKeyByBlob ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hUnwrappingKey, // in
+ UINT32 cWrappedKeyBlobSize, // in
+ BYTE* rgbWrappedKeyBlob, // in
+ TCS_AUTH* pAuth, // in, out
+ TCS_KEY_HANDLE* phKeyTCSI, // out
+ TCS_KEY_HANDLE* phKeyHMAC // out
+ );
+
+TPM_RESULT TCSP_GetPubKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey, // in
+ TCS_AUTH* pAuth, // in, out
+ UINT32* pcPubKeySize, // out
+ BYTE** prgbPubKey // out
+ );
+
+TPM_RESULT TCSP_EvictKey ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE hKey // in
+ );
+
+TPM_RESULT TCSP_Sign ( TCS_CONTEXT_HANDLE hContext, // in
+ TCS_KEY_HANDLE keyHandle, // in
+ UINT32 areaToSignSize, // in
+ BYTE* areaToSign, // in
+ TCS_AUTH* privAuth, // in, out
+ UINT32* sigSize, // out
+ BYTE** sig // out
+ );
+
+TPM_RESULT TCSP_GetRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32* bytesRequested, // in, out
+ BYTE** randomBytes // out
+ );
+
+TPM_RESULT TCSP_StirRandom ( TCS_CONTEXT_HANDLE hContext, // in
+ UINT32 inDataSize, // in
+ BYTE* inData // in
+ );
+
+TPM_RESULT TCSP_ReadPubek ( TCS_CONTEXT_HANDLE hContext, // in
+ TPM_NONCE antiReplay, // in
+ UINT32* pubEndorsementKeySize, // out
+ BYTE** pubEndorsementKey, // out
+ TPM_DIGEST* checksum // out
+ );
+
+
+// Non-Standard TCSP call to give direct access to TransmitData.
+// Key and Auth Management is done before transfering command to TDDL.
+TPM_RESULT TCSP_RawTransmitData(UINT32 inDataSize, // in
+ BYTE *inData, // in
+ UINT32 *outDataSize,// in/out
+ BYTE *outData); // out
+
+#endif //TCS_H
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tpmddl.c
+//
+// This file defines the TDDLI API
+//
+// ==================================================================
+
+#ifndef __TPMDDL_H__
+#define __TPMDDL_H__
+
+#define TDDL_CAP_PROP_MANUFACTURER 0x0001
+
+#define TDDL_E_FAIL 1
+#define TDDL_E_SUCCESS 0
+#define TDDL_SUCCESS 0
+
+typedef unsigned int TDDL_UINT32;
+typedef TDDL_UINT32 TDDL_RESULT;
+typedef unsigned char TDDL_BYTE;
+
+TDDL_RESULT TDDL_Open();
+void TDDL_Close();
+TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize);
+TDDL_RESULT TDDL_GetStatus();
+TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap,
+ TDDL_UINT32 sub,
+ TDDL_BYTE* buffer,
+ TDDL_UINT32* size);
+
+#endif // __TPMDDL_H__
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "tcg.h"
+#include "buffer.h"
+#include "log.h"
+#include "tpmddl.h"
+
+// flag to track whether TDDL has been opened
+static int g_TDDL_open = 0;
+static int g_fd = -1; // the fd to the TPM
+
+TPM_RESULT
+TDDL_TransmitData( TDDL_BYTE* in,
+ TDDL_UINT32 insize,
+ TDDL_BYTE* out,
+ TDDL_UINT32* outsize) {
+ TPM_RESULT status = TPM_SUCCESS;
+ TDDL_UINT32 i;
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
+ for(i = 0 ; i < insize ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ ssize_t size = 0;
+ int fd = g_fd;
+
+ // send the request
+ size = write (fd, in, insize);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "write() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+ else if ((TDDL_UINT32) size < insize) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", size, insize);
+ // ... ?
+ }
+
+ // read the response
+ size = read (fd, out, TCPA_MAX_BUFFER_LENGTH);
+ if (size < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "read() failed");
+ ERRORDIE (TPM_IOERROR);
+ }
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
+ for(i = 0 ; i < size ; i++)
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
+
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ *outsize = size;
+ // close connection
+ goto egress;
+
+ abort_egress:
+ egress:
+ return status;
+}
+
+TPM_RESULT TDDL_Open() {
+
+ TDDL_RESULT status = TDDL_SUCCESS;
+ int fd = -1;
+
+ if (g_TDDL_open)
+ return TPM_FAIL;
+
+ fd = open ("/dev/tpm0", O_RDWR);
+ if (fd < 0) {
+ vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed");
+ return TPM_IOERROR;
+ }
+
+ g_fd = fd;
+ g_TDDL_open = 1;
+
+ return status;
+}
+
+void TDDL_Close() {
+ if (! g_TDDL_open)
+ return;
+
+ if (g_fd>= 0) {
+ if (close(g_fd) < 0)
+ vtpmlogerror(VTPM_LOG_TXDATA, "closeing tpm failed");
+
+ g_fd = -1;
+ }
+
+ g_TDDL_open = 0;
+
+}
--- /dev/null
+XEN_ROOT = ../../..\r
+include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk\r
+\r
+BIN = libTCGUtils.a\r
+\r
+all: build\r
+\r
+build: $(BIN)\r
+\r
+install: build\r
+\r
+clean:\r
+ rm -f *.a *.so *.o *.rpm $(DEP_FILES)\r
+\r
+mrproper: clean\r
+\r
+$(BIN): $(OBJS)\r
+ $(AR) rcs $(BIN) $(OBJS)\r
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// bsg.cpp
+//
+// This file will handle all the TPM Byte Stream functions
+//
+// ==================================================================
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <malloc.h>
+#include "tcg.h"
+#include "crypto.h"
+#include "bsg.h"
+#include "log.h"
+
+static int g_log_recursion_level = 0;
+
+// a largest buffer size. if we get a buf size bigger than this when unpacking,
+// will complain!
+#define BSG_MAX_BUF_SIZE (1<<18)
+
+#define bsglog(fmt, ...) do { \
+ int __i; \
+ for (__i=0; __i < g_log_recursion_level; __i++) { \
+ vtpmloginfomore (VTPM_LOG_BSG, "%s", " "); \
+ } \
+ vtpmloginfomore (VTPM_LOG_BSG, fmt, __VA_ARGS__); \
+ } while (0)
+
+
+// FIXME: trigger the selfcheck--need to use glibc hook to do this
+//BOOL dummy1 = BSG_static_selfcheck();
+
+
+// Interpretting Types
+// -------------------
+//
+// Incoming Types are composed of two parts {format, info} squished into a
+// BSG_UINT32. The first 4 bits is a format spec indicating what type of
+// data it is. If the first 4 bits are zero the info corresponds to a value in
+// BSG_s_fmt[]. This is a structure whose composition is described in
+// BSG_s_fmt[]. If the value is non-zero, info corresponds to the size of the
+// data (in bytes) being passed in. For example a UINT32 being passed in would
+// have a format of (__FMT_CONST | 4). If both, the format and info are zero,
+// this is interpretted as the end of the structure, and the result is returned.
+
+// these flags are mutually exclusive, so I'll just make them
+// format values which indicate the semantics of the 'info' part and the source
+// data. The above description has been accordingly adjusted.
+
+// format values for determining what type of data the incoming type is
+// it's a 4 bit value, occupying the high 4 bits
+#define __FMT_CONST (1UL << 28) // Constant sized value
+#define __FMT_DATA (2UL << 28) // Believed to be raw data NOT {size,data}
+#define __FMT_SIZE (3UL << 28) // A size. Used in FMT_SIZE??_DATA.
+#define __FMT_HSIZE (4UL << 28) // A number of handles
+#define __FMT_PACKED (5UL << 28) // 'info' is unused; the source data consists
+ // of {size32, data} but we're to pack only the
+ // data as that is already packed, and so
+ // can/must be unpacked without
+ // explicitly reading it size
+
+#define __FMT_MASK 0x0FFFFFFFUL // this masks out the 4-bit format
+#define __FMT_MASK_SIZE(type) ((type) & __FMT_MASK)
+#define __FMT_MASK_FORMAT(type) ((type) & (~__FMT_MASK))
+
+// constant (8/16/32-bits)
+#define FMT_U8 (__FMT_CONST | 1UL)
+#define FMT_U16 (__FMT_CONST | 2UL)
+#define FMT_U32 (__FMT_CONST | 4UL)
+
+// const with a compiler-computed size
+#define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type))
+
+// other data (size bytes)
+// Used primarily for DIGESTS -> FMT_DATA(20)
+#define FMT_DATA(size) (__FMT_DATA | ((BSG_UINT32) (size) & __FMT_MASK))
+
+// 16/32-bit size followed by N bytes of data
+#define FMT_SIZE16_DATA (__FMT_SIZE | 2UL)
+#define FMT_SIZE32_DATA (__FMT_SIZE | 4UL)
+
+// 16-bit size followed by N key handles
+#define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL)
+
+#define DIGEST_SIZE 20
+typedef BSG_UINT32 BSG_HANDLE;
+
+// TCPA_AUTH has 11 fields!
+#define MAX_FIELDS 11
+typedef struct BSG_Format
+{
+ BSG_Type type;
+ const char* name;
+ BSG_UINT32 fields[MAX_FIELDS + 1];
+} BSG_Format;
+
+/*
+ * TCPA structure data formats
+ */
+// this has to be manually kept in sync with the
+// Type enum!! the static_selfcheck() function should be used regularly!
+static BSG_Format s_fmt[] =
+{
+ {BSG_TYPE_UINT32, "BSG_TYPE_UINT32", {FMT_U32, 0}},
+ {BSG_TYPE_UINT16, "BSG_TYPE_UINT16", {FMT_U16, 0}},
+ {BSG_TYPE_BYTE, "BSG_TYPE_BYTE", {FMT_U8, 0}},
+ {BSG_TYPE_BOOL, "BSG_TYPE_BOOL", {FMT_U8, 0}},
+ {BSG_TPM_SIZE32_DATA, "BSG_TPM_SIZE32_DATA", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_TAG, "BSG_TPM_TAG", {FMT_SIZEOF(TPM_TAG), 0}},
+ {BSG_TPM_HANDLE, "BSG_TPM_HANDLE", {FMT_SIZEOF(TPM_HANDLE), 0}},
+ {BSG_TPM_RESULT, "BSG_TPM_RESULT", {FMT_SIZEOF(TPM_RESULT), 0}},
+ {BSG_TPM_RESOURCE_TYPE, "BSG_TPM_RESOURCE_TYPE", {FMT_SIZEOF(TPM_RESOURCE_TYPE), 0}},
+ {BSG_TPM_COMMAND_CODE, "BSG_TPM_COMMAND_CODE", {FMT_U32, 0}},
+ {BSG_TPM_AUTH_DATA_USAGE, "BSG_TPM_AUTH_DATA_USAGE", {FMT_U8, 0}},
+ {BSG_TPM_ALGORITHM_ID, "BSG_TPM_ALGORITHM_ID", {FMT_U32, 0}},
+ {BSG_TPM_PROTOCOL_ID, "BSG_TPM_PROTOCOL_ID", {FMT_SIZEOF(TPM_PROTOCOL_ID), 0}},
+ {BSG_TPM_KEY_USAGE, "BSG_TPM_KEY_USAGE", {FMT_U16, 0}},
+ {BSG_TPM_ENC_SCHEME, "BSG_TPM_ENC_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_SIG_SCHEME, "BSG_TPM_SIG_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_MIGRATE_SCHEME, "BSG_TPM_MIGRATE_SCHEME", {FMT_U16, 0}},
+ {BSG_TPM_KEY_FLAGS, "BSG_TPM_KEY_FLAGS", {FMT_U32, 0}},
+
+ {BSG_TPM_AUTHDATA, "BSG_TPM_AUTHDATA", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_SECRET, "BSG_TPM_SECRET", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_ENCAUTH, "BSG_TPM_ENCAUTH", {BSG_TPM_AUTHDATA, 0}},
+ {BSG_TPM_PAYLOAD_TYPE, "BSG_TPM_PAYLOAD_TYPE", {FMT_SIZEOF(TPM_PAYLOAD_TYPE), 0}},
+
+ {BSG_TPM_VERSION, "BSG_TPM_VERSION", {FMT_DATA(4), 0}}, // vers 1.2
+ {BSG_TPM_DIGEST, "BSG_TPM_DIGEST", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_COMPOSITE_HASH, "BSG_TPM_COMPOSITE_HASH", {BSG_TPM_DIGEST, 0}},
+ {BSG_TPM_CHOSENID_HASH, "BSG_TPM_CHOSENID_HASH", {BSG_TPM_DIGEST, 0}},
+
+ {BSG_TPM_NONCE, "BSG_TPM_NONCE", {FMT_DATA(DIGEST_SIZE), 0}},
+ {BSG_TPM_KEY_HANDLE, "BSG_TPM_KEY_HANDLE", {FMT_SIZEOF(TPM_KEY_HANDLE), 0}},
+ {BSG_TPM_KEY_HANDLE_LIST, "BSG_TPM_KEY_HANDLE_LIST",
+ {FMT_SIZE16_HANDLES, 0}},
+
+ {BSG_TPM_KEY_PARMS, "BSG_TPM_KEY_PARMS", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_RSA_KEY_PARMS, "BSG_TPM_RSA_KEY_PARMS", {
+ FMT_U32, FMT_U32, FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_PUBKEY, "BSG_TPM_STORE_PUBKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_PUBKEY, "BSG_TPM_PUBKEY", {BSG_TPM_KEY_PARMS, BSG_TPM_STORE_PUBKEY, 0}},
+ {BSG_TPM_KEY, "BSG_TPM_KEY", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA, // the PCR_INFO
+ BSG_TPM_STORE_PUBKEY,
+ FMT_SIZE32_DATA, // the encrypted part
+ 0}},
+
+ {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", {
+ BSG_TPM_PUBKEY,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_DIGEST, 0}},
+
+ {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", {
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_RESULT, 0 }},
+
+ {BSG_TCPA_EVENT_CERT, "TCPA_EVENT_CERT", {
+ BSG_TPM_DIGEST,
+ BSG_TPM_DIGEST,
+ FMT_DATA(2),
+ FMT_SIZE32_DATA, 0}},
+
+ {BSG_TPM_PCR_SELECTION, "BSG_TPM_PCR_SELECTION", {FMT_SIZE16_DATA, 0} },
+ {BSG_TPM_PCR_COMPOSITE, "BSG_TPM_PCR_COMPOSITE", { BSG_TPM_PCR_SELECTION,
+ FMT_SIZE32_DATA,
+ 0} },
+
+ {BSG_TPM_PCR_INFO, "BSG_TPM_PCR_INFO", { BSG_TPM_PCR_SELECTION,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_COMPOSITE_HASH,
+ 0} },
+
+
+ {BSG_TPM_STORED_DATA, "BSG_TPM_STORED_DATA", {
+ BSG_TPM_VERSION,
+ FMT_SIZE32_DATA,
+ FMT_SIZE32_DATA,
+ 0}},
+ {BSG_TPM_SYMMETRIC_KEY, "BSG_TPM_SYMMETRIC_KEY", {
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_ENC_SCHEME,
+ FMT_SIZE16_DATA,
+ 0}},
+ {BSG_TPM_STORE_PRIVKEY, "BSG_TPM_STORE_PRIVKEY", {FMT_SIZE32_DATA, 0}},
+ {BSG_TPM_STORE_ASYMKEY, "BSG_TPM_STORE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+ {BSG_TPM_MIGRATE_ASYMKEY, "BSG_TPM_MIGRATE_ASYMKEY", {
+ BSG_TPM_PAYLOAD_TYPE,
+ BSG_TPM_SECRET,
+ BSG_TPM_DIGEST,
+ FMT_U32,
+ BSG_TPM_STORE_PRIVKEY,
+ 0}},
+
+ {BSG_TPM_QUOTE_INFO, "BSG_TPM_QUOTE_INFO", {
+ BSG_TPM_VERSION,
+ FMT_DATA(4),
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_NONCE,
+ 0}},
+
+ {BSG_TPM_IDENTITY_CONTENTS, "BSG_TPM_IDENTITY_CONTENTS", {
+ BSG_TPM_VERSION,
+ FMT_U32,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_PUBKEY,
+ 0}},
+
+ {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}},
+
+ {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", {
+ FMT_U8,
+ FMT_U8,
+ 0}},
+
+ {BSG_TCS_AUTH, "TCS_AUTH", {
+ BSG_TYPE_UINT32,
+ BSG_TPM_NONCE,
+ BSG_TPM_NONCE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_AUTHDATA,
+ 0}},
+
+ {BSG_TPM_KEY_NONSENSITIVE, "BSG_TPM_KEY_NONSENSITIVE", {
+ BSG_TPM_VERSION,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_KEY_PARMS,
+ FMT_SIZE32_DATA,
+ BSG_TPM_STORE_PUBKEY,
+ 0}},
+
+ {BSG_PACKED, "BSG_PACKED", {
+ __FMT_PACKED,
+ 0 }},
+
+ {BSG_TYPE_MAX, "", {0}},
+};
+
+
+static const BSG_Format* find_format (BSG_Type t) {
+ BSG_Format * f = s_fmt;
+
+ if (t >= BSG_TYPE_MAX) {
+ return NULL;
+ }
+
+ // WARNING: this depends on the enum and s_fmt[] array being in sync! make
+ // sure to run the static_selfcheck() to make sure
+ f = s_fmt + (t - BSG_TYPE_FIRST);
+
+ return f;
+}
+
+//
+// a consistency-checking routine which can be run at compile time
+// (ie. immediately after compilation)
+//
+// tasks:
+// - verify that s_fmt has one entry per Type t, and that entry is at s_fmt[t]
+//
+// conditions:
+// - need that s_fmt[0] is the first type listed in the Type enum! ie the first
+// Type has value 0, not 1
+//
+// FIXME: should have a function be passed in here which is called if the test
+// fails. Then the caller can decide what to do: abort, notify, whatever
+//
+BOOL BSG_static_selfcheck ()
+{
+ int i;
+
+ for (i=BSG_TYPE_FIRST; i <= BSG_TYPE_MAX; i++) {
+ if (s_fmt[i - BSG_TYPE_FIRST].type != i) {
+ bsglog ("%s\n", "BSG: static_selfcheck failed!\n");
+ bsglog ("failure at %i, allegedly %s\n",
+ i, s_fmt[i - BSG_TYPE_FIRST].name);
+ abort();
+ return FALSE;
+ }
+ }
+
+ bsglog ("%s\n", "BSG: static_selfcheck success!");
+ return TRUE;
+}
+
+
+/**
+ * Flatten a TCPA structure into a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * @dst: (OUT) flattened data
+ * Returns: Flattened size or -1 for unknown types
+ */
+// make it so that it can just run through the whole process and return
+// the packed size, without packing anything. this will be done if dst is NULL.
+static int BSG_Pack_private(BSG_Type type, const BSG_BYTE** src, BSG_BYTE* dst)
+{
+ // check incoming parameters
+ if (*src == NULL)
+ return 0;
+
+ const BSG_BYTE* s = *src;
+ BSG_BYTE* d = dst;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) // We are dealing with a fixed length value eg. UINT32
+ {
+ BSG_UINT32 val = 0;
+ switch (size) {
+ case 1: val = * (BYTE*) s; break;
+ case 2: val = * (unsigned short*) s; break;
+ case 4: val = * (BSG_UINT32*) s; break;
+ }
+ if (dst)
+ BSG_PackConst(val, size, d);
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) { // We are dealing with raw data. Not sure when
+ // this is used.
+
+ if (dst) {
+ bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d);
+ memcpy(d, s, size);
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) { // It's a size, followed by that much data or handles
+
+ BSG_UINT32 psize = 0;
+ switch (size) {
+ case 1: psize = * (BYTE*) s; break;
+ case 2: psize = * (unsigned short*) s; break;
+ case 4: psize = * (BSG_UINT32*) s; break;
+ }
+
+ if (dst)
+ BSG_PackConst(psize, size, d);
+
+ s += size;
+ d += size;
+
+ // now 's' points to an address, so cast it to BSG_BYTE**
+ const BSG_BYTE* pdata = * ((BSG_BYTE**) s);
+ s += sizeof(BSG_BYTE*);
+
+ if (format == __FMT_HSIZE) {// This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* d2 = (BSG_HANDLE*) d;
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++)
+ d2[i] = BSG_UnpackConst((BSG_BYTE*)(p2 + i), 4);
+
+ }
+ d += psize * sizeof(BSG_HANDLE);
+ } else {// If it's not psize handles, it's psize data.
+ if (psize > 0) {
+ if (dst) {
+ bsglog ("BSG: __FMT_SIZE, size=%d, src=%p, dst=%p\n",
+ psize, pdata, d);
+ memcpy(d, pdata, psize);
+ }
+ }
+ d += psize;
+ }
+ } else if (format == __FMT_PACKED) {
+ // the source buffer is a pack_constbuf_t, which has a size and a
+ // pointer. just copy the buffer value, the size is not included in the
+ // output stream.
+ pack_constbuf_t * buf = (pack_constbuf_t*) s;
+
+ if (dst) {
+ bsglog ("BSG: __FMT_PACKED, size=%d, src=%p, dst=%p\n",
+ buf->size, buf->data, d);
+ memcpy(d, buf->data, buf->size);
+ }
+
+ s += buf->size;
+ d += buf->size;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmloginfo(VTPM_LOG_BSG, "BSG_Pack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ if (dst)
+ bsglog ("BSG_Pack type %s\n", x->name);
+
+
+ // iterate through the fields
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize;
+
+ g_log_recursion_level++;
+ fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL);
+ g_log_recursion_level--;
+
+ if (fsize <= 0)
+ return fsize;
+
+ d += fsize;
+ }
+ } else {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format);
+ return -1;
+ }
+
+ *src = s;
+ return (d - dst);
+}
+
+/**
+ * Unflatten a TCPA structure from a buffer in big-endian format
+ * @type: TCPA structure type
+ * @src: flattened data
+ * @dst: (IN) TCPA structure (OUT) end of TCPA structure
+ * Returns: Flattened size
+ * Note: Returns flattened size NOT the unpacked structure size
+ */
+static int BSG_Unpack_private(BSG_Type type, const BSG_BYTE* src, BSG_BYTE** dst) {
+ // check incoming parameters
+ if (src == NULL)
+ return 0;
+
+
+ const BSG_BYTE* s = src;
+ BSG_BYTE* d = dst ? *dst:NULL;
+ if (dst && !d)
+ dst = NULL;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if (format == __FMT_CONST) {// We are dealing with a fixed length value ie. UINT32
+
+ BSG_UINT32 val = BSG_UnpackConst(s, size);
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) val; break;
+ case 2: *(unsigned short*) d = (unsigned short) val; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) val; break;
+ }
+ }
+
+ s += size;
+ d += size;
+ } else if (format == __FMT_DATA) {// We are dealing with raw data. Not sure when this is used.
+ if (dst)
+ memcpy(d, s, size);
+
+ d += size;
+ s += size;
+ } else if (format == __FMT_SIZE || format == __FMT_HSIZE) {// It's a size, followed by that much data or handles
+
+ BSG_UINT32 psize = BSG_UnpackConst(s, size);
+
+ if (psize > BSG_MAX_BUF_SIZE) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack runs into var-sized data bigger than %u bytes!!\n",
+ BSG_MAX_BUF_SIZE);
+ return -1;
+ }
+
+ if (dst) {
+ switch (size) {
+ case 1: *(BYTE *) d = (BSG_BYTE) psize; break;
+ case 2: *(unsigned short*) d = (unsigned short) psize; break;
+ case 4: *(BSG_UINT32*) d = (BSG_UINT32) psize; break;
+ }
+ }
+
+ s += size;
+ d += size;
+
+ BSG_BYTE* pdata = NULL;
+
+ if (psize) {
+ if (format == __FMT_HSIZE) { // This is a list of psize Handles
+ if (dst) {
+ BSG_HANDLE* s2 = (BSG_HANDLE*) s;
+ pdata = (BSG_BYTE *)malloc(psize * sizeof(BSG_HANDLE));
+ if (!pdata)
+ return -1;
+
+ BSG_HANDLE* p2 = (BSG_HANDLE*) pdata;
+ BSG_UINT32 i;
+ for (i = 0; i < psize; i++) {
+ BSG_PackConst(s2[i], 4, (BSG_BYTE*)(p2 + i));
+ }
+ }
+ s += psize * sizeof(BSG_HANDLE);
+ } else { // If it's not psize handles, it's psize data.
+ if (dst) {
+ pdata = (BSG_BYTE *)malloc(sizeof(BSG_BYTE) * psize);
+ if (!pdata)
+ return -1;
+ memcpy(pdata, s, psize);
+ }
+ s += psize;
+ }
+ }
+ if (dst)
+ *(void**) d = pdata;
+
+ d += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking!
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack() called with format __FMT_PACKED. "
+ "This does not make sense\n");
+
+ return -1;
+ } else if (format == 0) {// No flags are set. This is a structure & it should
+ // be looked up in the bsg_s_fmt[]
+
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack: cannot find type %d\n", type);
+ return -1;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++) {
+ int fsize = BSG_Unpack_private((BSG_Type) *f, s, dst ? &d:NULL);
+ if (fsize <= 0)
+ return fsize;
+ s += fsize;
+ }
+ }
+
+ if (dst)
+ *dst = d;
+ return (s - src);
+}
+
+/**
+ * Free memory associated with unpacked TCPA structure
+ * @type: TCPA structure type
+ * @src: (IN) TCPA structure (OUT) end of TCPA structure
+ * Note: Destroy should be called on all structures created with Unpack
+ * to ensure that any allocated memory is freed
+ */
+static void BSG_Destroy_private(BSG_Type type, BSG_BYTE** src) {
+ BSG_BYTE* s = *src;
+
+ BSG_UINT32 size = __FMT_MASK_SIZE(type);
+ BSG_UINT32 format = __FMT_MASK_FORMAT(type);
+
+ if ((src == NULL) || (*src == NULL)) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n");
+ return;
+ }
+
+ if (format == __FMT_CONST || format == __FMT_DATA)
+ s += size;
+ else if (format == __FMT_SIZE || format == __FMT_HSIZE) {
+ s += size;
+ BSG_BYTE* ptr = *(BSG_BYTE**) s;
+ if (ptr)
+ free(ptr);
+ s += sizeof(void*);
+ } else if (format == __FMT_PACKED) {
+
+ // this doesn't make sense for unpacking, hence also for Destroy()
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED. "
+ "This does not make sense\n");
+
+ return;
+ } else if (format == 0) {
+ const BSG_Format* x = find_format (type);
+ if (x == NULL) {
+ vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type);
+ return;
+ }
+
+ const BSG_UINT32* f = x->fields;
+ for (; *f; f++)
+ BSG_Destroy_private((BSG_Type) *f, &s);
+ }
+
+ *src = s;
+}
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst)
+{
+ const BSG_BYTE* src2 = (const BSG_BYTE*) src;
+ return BSG_Pack_private(type, &src2, dst);
+}
+
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst)
+{
+ BSG_BYTE* dst2 = (BSG_BYTE*) dst;
+ return BSG_Unpack_private(type, src, dst ? &dst2:NULL);
+}
+
+void BSG_Destroy(BSG_Type type, void* src)
+{
+ BSG_BYTE* src2 = (BSG_BYTE*) src;
+ BSG_Destroy_private(type, &src2);
+}
+
+/**
+ * Pack a 8/16/32-bit constant into a buffer in big-endian format
+ * @val: constant value
+ * @size: constant size in bytes (1, 2, or 4)
+ * @dst: (OUT) buffer
+ */
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) {
+ bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst);
+
+ switch (size) {
+ case 4:
+ dst[0] = (BSG_BYTE)((val >> 24) & 0xff);
+ dst[1] = (BSG_BYTE)((val >> 16) & 0xff);
+ dst[2] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[3] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 2:
+ dst[0] = (BSG_BYTE)((val >> 8) & 0xff);
+ dst[1] = (BSG_BYTE)(val & 0xff);
+ break;
+ case 1:
+ dst[0] = (BSG_BYTE)(val & 0xff);
+ break;
+ }
+}
+
+/**
+ * Unpack a 8/16/32-bit constant from a buffer in big-endian format
+ * @src: buffer
+ * @size: constant size in bytes (1, 2, or 4)
+ */
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) {
+ BSG_UINT32 val = 0;
+
+ if (src == NULL)
+ return 0;
+
+ switch (size) {
+ case 4:
+ val = (((BSG_UINT32) src[0]) << 24
+ | ((BSG_UINT32) src[1]) << 16
+ | ((BSG_UINT32) src[2]) << 8
+ | (BSG_UINT32) src[3]);
+ break;
+ case 2:
+ val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]);
+ break;
+ case 1:
+ val = (BSG_UINT32) src[0];
+ break;
+ }
+ return val;
+}
+
+// Pack a list of parameters. Beware not to send values, but rather you must
+// send a pointer to your values Instead. This includes UINT32's.
+int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) {
+ int ParamNumber;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size=0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ //Strangeness with int is because gcc wanted an int rather than a enum of ints.
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+ size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size);
+ }
+
+ va_end (paramList);
+
+ return size;
+}
+
+// Unpack a list of parameters.
+int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type format;
+ BSG_BYTE* val = NULL;
+ int size = 0;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ format = (BSG_Type) va_arg( paramList, int );
+ val = va_arg( paramList, BSG_BYTE* );
+
+ size += BSG_Unpack(format, src + size, val);
+ }
+
+ va_end( paramList );
+
+ return size;
+}
+
+// Destroy any memory allocated by calls to unpack
+void BSG_DestroyList(int ParamCount, ... ) {
+ int ParamNumber = 0;
+ BSG_Type argType;
+ BSG_BYTE* paramValue = NULL;
+
+ va_list paramList;
+ va_start( paramList, ParamCount );
+
+ for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
+ argType = (BSG_Type) va_arg( paramList, int );
+ paramValue = va_arg( paramList, BSG_BYTE* );
+
+ BSG_Destroy(argType, paramValue);
+ }
+
+ va_end( paramList );
+
+ return;
+}
+
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
+ int i;
+
+ for (i = 0; i < numParams; i++)
+ BSG_Destroy (params[i].type, params[i].addr);
+
+ return TPM_SUCCESS;
+}
+
+
+//
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later
+//
+
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) {
+ int size = BSG_Pack (type, src, NULL);
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ size = BSG_Pack(type, src, dest);
+ *o_dst = dest;
+ return size;
+}
+
+
+
+int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
+ va_list args;
+ int size;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (NULL, ParamCount, args);
+ va_end (args);
+
+ BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
+ if (dest == NULL)
+ return -1;
+
+ va_start (args, ParamCount);
+ size = BSG_PackList (dest, ParamCount, args);
+ va_end (args);
+
+ *outBuffer = dest;
+ return size;
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// bsg.h
+//
+// This file contains API's for the TPM Byte Stream functions
+//
+// ==================================================================
+
+#ifndef __BSG_H__
+#define __BSG_H__
+
+#include <stdarg.h>
+#include "buffer.h"
+
+typedef unsigned int BSG_UINT32;
+typedef unsigned char BSG_BYTE;
+
+// forward decl
+struct pack_const_tuple_t;
+
+struct pack_tuple_t;
+
+
+/**
+ * Byte stream generator
+ */
+// this has to be manually kept in sync with the
+// s_fmt array!!
+// but now we have a self-check function which can make sure things are well
+// (if used!)
+typedef enum BSG_Type
+{
+ BSG_TYPE_FIRST = 1,
+ BSG_TYPE_UINT32 = 1, // start at 1 so that Type 0 only serves as an
+ // unused/special value
+ BSG_TYPE_UINT16,
+ BSG_TYPE_BYTE,
+ BSG_TYPE_BOOL,
+ BSG_TPM_SIZE32_DATA, // a 32 bit unsigned size, followed by
+ // a pointer to that much data. can pass a
+ // struct pack_buf_t as the param
+ BSG_TPM_TAG,
+ BSG_TPM_HANDLE,
+ BSG_TPM_RESULT,
+ BSG_TPM_RESOURCE_TYPE,
+ BSG_TPM_COMMAND_CODE,
+ BSG_TPM_AUTH_DATA_USAGE,
+ BSG_TPM_ALGORITHM_ID,
+ BSG_TPM_PROTOCOL_ID,
+ BSG_TPM_KEY_USAGE,
+ BSG_TPM_ENC_SCHEME,
+ BSG_TPM_SIG_SCHEME,
+ BSG_TPM_MIGRATE_SCHEME,
+ BSG_TPM_KEY_FLAGS,
+ BSG_TPM_AUTHDATA,
+ BSG_TPM_SECRET,
+ BSG_TPM_ENCAUTH,
+ BSG_TPM_PAYLOAD_TYPE,
+
+ BSG_TPM_VERSION,
+ BSG_TPM_DIGEST,
+ BSG_TPM_COMPOSITE_HASH,
+ BSG_TPM_CHOSENID_HASH,
+ BSG_TPM_NONCE,
+ BSG_TPM_KEY_HANDLE,
+ BSG_TPM_KEY_HANDLE_LIST,
+ BSG_TPM_KEY_PARMS,
+ BSG_TPM_RSA_KEY_PARMS,
+ BSG_TPM_STORE_PUBKEY,
+ BSG_TPM_PUBKEY,
+ BSG_TPM_KEY,
+
+ BSG_TPM_MIGRATIONKEYAUTH,
+ BSG_TCPA_AUDIT_EVENT,
+ BSG_TCPA_EVENT_CERT,
+ BSG_TPM_PCR_SELECTION,
+ BSG_TPM_PCR_COMPOSITE,
+ BSG_TPM_PCR_INFO,
+ BSG_TPM_STORED_DATA,
+ BSG_TPM_SYMMETRIC_KEY,
+ BSG_TPM_STORE_PRIVKEY,
+ BSG_TPM_STORE_ASYMKEY,
+ BSG_TPM_MIGRATE_ASYMKEY,
+ BSG_TPM_QUOTE_INFO,
+ BSG_TPM_IDENTITY_CONTENTS,
+ BSG_TPM_PCRVALUE,
+ BSG_TCPA_PCR_FLAGS,
+ BSG_TCS_AUTH,
+
+ // this is the BSG_TPM_KEY struct without the encData field
+ BSG_TPM_KEY_NONSENSITIVE,
+
+ BSG_PACKED,
+
+ BSG_TYPE_MAX
+} BSG_Type;
+
+struct pack_const_tuple_t {
+ BSG_Type type;
+ const void * addr;
+};
+
+
+typedef struct pack_tuple_t {
+ BSG_Type type;
+ void * addr;
+} pack_tuple_t;
+
+int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst);
+int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst);
+void BSG_Destroy(BSG_Type type, void* src);
+
+// wrappers of Pack and PackList which malloc the ouput buffer. to be freed
+// by the caller later. returns size of allocated buffer, or -1 in case
+// allocation failed
+int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst);
+int BSG_PackListMalloc (BSG_BYTE** outBuffer, int ParamCount, ... );
+
+// a va_list version of PackList
+int BSG_PackList(BSG_BYTE* outBuffer, int ParamCount, ... );
+int BSG_UnpackList(const BSG_BYTE* inBuffer, int ParamCount, ... );
+void BSG_DestroyList(int ParamCount, ... );
+
+// wrapper of PackList which uses a buffer_t
+TPM_RESULT BSG_PackListBuf (buffer_t * o_buf, int ParamCount, ...);
+
+// and a tuple version
+TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]);
+
+void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst);
+BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size);
+
+BOOL BSG_static_selfcheck ();
+
+#endif
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+#include "tcg.h"
+#include "bsg.h"
+#include "buffer.h"
+
+static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize);
+
+//
+// buffer functions!
+//
+
+TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE* initval) {
+ if (initsize == 0) {
+ memset(buf, 0, sizeof(*buf));
+ return TPM_SUCCESS;
+ }
+
+
+ buf->bytes = (BYTE*) malloc (initsize);
+ if (buf->bytes == NULL)
+ return TPM_RESOURCES;
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+
+ if (initval)
+ memcpy (buf->bytes, initval, initsize);
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_convert (buffer_t * buf, tpm_size_t initsize, BYTE* initval) {
+
+ buf->size = initsize;
+ buf->alloc_size = initsize;
+ buf->bytes = initval;
+
+ buf->is_owner = TRUE;
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src) {
+ TPM_RESULT status = buffer_init (buf, src->size, src->bytes);
+ buf->is_owner = TRUE;
+
+ return status;
+}
+
+
+
+// make an alias to a constant array
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE* val) {
+ // TODO: try to enforce the const things somehow!
+ buf->bytes = (BYTE*) val;
+ buf->size = size;
+ buf->alloc_size = 0; // this field is now unneeded
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t len) {
+ if (offset + len > b->size) {
+ return TPM_NOSPACE;
+ }
+
+ buf->bytes = b->bytes + offset;
+ buf->size = len > 0 ? len : b->size - offset;
+
+ //VS/ buf->alloc_size = 0;
+ if (len ==0)
+ buf->alloc_size = b->alloc_size - offset;
+ else
+ buf->alloc_size = MIN(b->alloc_size - offset, len);
+
+
+ buf->is_owner = FALSE;
+
+ return TPM_SUCCESS;
+}
+
+
+// copy into the start of dest
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (dest->alloc_size < src->size) {
+ status = buffer_priv_realloc (dest, src->size);
+ STATUSCHECK (status);
+ }
+
+ memcpy (dest->bytes, src->bytes, src->size);
+ dest->size = src->size;
+
+ //VS/ dest->is_owner = TRUE;
+
+ abort_egress:
+
+ return status;
+}
+
+
+
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b) {
+ return (a->size == b->size && memcmp (a->bytes, b->bytes, a->size) == 0);
+}
+
+
+void buffer_memset (buffer_t * buf, BYTE b) {
+ memset (buf->bytes, b, buf->size);
+}
+
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* bytes) {
+ TPM_RESULT status = TPM_SUCCESS;
+
+ if (buf->alloc_size < buf->size + len) {
+ status = buffer_priv_realloc (buf, buf->size + len);
+ STATUSCHECK (status);
+ }
+
+ memcpy (buf->bytes + buf->size, bytes, len);
+
+ buf->size += len;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+tpm_size_t buffer_len (const buffer_t* buf) {
+ return buf->size;
+}
+
+TPM_RESULT buffer_free (buffer_t * buf) {
+ if (buf && buf->is_owner && buf->bytes != NULL) {
+ free (buf->bytes);
+ buf->bytes = NULL;
+ }
+
+ return TPM_SUCCESS;
+}
+
+TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize) {
+
+ // we want to realloc to twice the size, or the new size, whichever
+ // bigger
+
+ BYTE * tmpbuf = NULL;
+
+ newsize = MAX (buf->alloc_size * 2, newsize);
+
+ tmpbuf = (BYTE*) realloc (buf->bytes, newsize);
+ if (tmpbuf == NULL)
+ return TPM_SIZE;
+
+
+ buf->bytes = tmpbuf;
+ buf->alloc_size = newsize;
+
+ return TPM_SUCCESS;
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_BUFFER_H__
+#define __VTPM_BUFFER_H__
+
+#include <stddef.h> // for pointer NULL
+#include "tcg.h"
+
+// structure to enable use of FMT_SIZE32_DATA in BSG_Unpack
+typedef struct pack_buf_t {
+ UINT32 size;
+ BYTE * data;
+} pack_buf_t;
+
+// and a const version for Pack
+typedef struct pack_constbuf_t {
+ UINT32 size;
+ const BYTE* data;
+} pack_constbuf_t;
+
+typedef UINT32 tpm_size_t;
+
+// first version, probably will be expanded...
+
+#define NULL_BUF {0,0,0,0}
+
+typedef struct {
+ // private!!
+ tpm_size_t size, alloc_size;
+ BYTE * bytes;
+
+ BOOL is_owner; // do we own this buffer, and need to free it?
+} buffer_t;
+
+// allocate the buffer if initsize > 0, copying over initval if provided
+TPM_RESULT buffer_init (buffer_t * buf,
+ tpm_size_t initsize,
+ const BYTE* initval);
+
+// Create a new buffer from a BYTE *. Use buffer_free to destroy original BYTE *
+TPM_RESULT buffer_init_convert (buffer_t * buf,
+ tpm_size_t initsize,
+ BYTE* initval);
+
+// make an alias to a constant array, no copying
+TPM_RESULT buffer_init_const (buffer_t * buf, tpm_size_t size, const BYTE* val);
+
+// make an alias into buf, with given offset and length
+// if len = 0, make the alias go to the end of buf
+TPM_RESULT buffer_init_alias (buffer_t * buf, const buffer_t * b,
+ tpm_size_t offset, tpm_size_t);
+
+// "copy constructor"
+TPM_RESULT buffer_init_copy (buffer_t * buf, const buffer_t * src);
+
+
+// copy into the start of a
+TPM_RESULT buffer_copy (buffer_t * dest, const buffer_t* src);
+
+// are they equal?
+BOOL buffer_eq (const buffer_t * a, const buffer_t * b);
+
+// set the buffer to a constant byte
+void buffer_memset (buffer_t * buf, BYTE b);
+
+tpm_size_t buffer_len (const buffer_t* buf);
+
+TPM_RESULT buffer_free (buffer_t * buf);
+
+TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* bytes);
+
+#endif // _TOOLS_H_
--- /dev/null
+hashtable.o: hashtable.c hashtable.h hashtable_private.h
+hashtable_itr.o: hashtable_itr.c hashtable.h hashtable_private.h \
+ hashtable_itr.h
+bsg.o: bsg.c tcg.h ../crypto/crypto.h ../crypto/sym_crypto.h buffer.h \
+ bsg.h log.h
+log.o: log.c buffer.h tcg.h
+buffer.o: buffer.c tcg.h bsg.h buffer.h
--- /dev/null
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@cl.cam.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/*
+Credit for primes table: Aaron Krowne
+ http://br.endernet.org/~akrowne/
+ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const unsigned int primes[] = {
+53, 97, 193, 389,
+769, 1543, 3079, 6151,
+12289, 24593, 49157, 98317,
+196613, 393241, 786433, 1572869,
+3145739, 6291469, 12582917, 25165843,
+50331653, 100663319, 201326611, 402653189,
+805306457, 1610612741
+};
+const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
+const float max_load_factor = 0.65;
+
+/*****************************************************************************/
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashf) (void*),
+ int (*eqf) (void*,void*))
+{
+ struct hashtable *h;
+ unsigned int pindex, size = primes[0];
+ /* Check requested hashtable isn't too large */
+ if (minsize > (1u << 30)) return NULL;
+ /* Enforce size as prime */
+ for (pindex=0; pindex < prime_table_length; pindex++) {
+ if (primes[pindex] > minsize) { size = primes[pindex]; break; }
+ }
+ h = (struct hashtable *)malloc(sizeof(struct hashtable));
+ if (NULL == h) return NULL; /*oom*/
+ h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
+ if (NULL == h->table) { free(h); return NULL; } /*oom*/
+ memset(h->table, 0, size * sizeof(struct entry *));
+ h->tablelength = size;
+ h->primeindex = pindex;
+ h->entrycount = 0;
+ h->hashfn = hashf;
+ h->eqfn = eqf;
+ h->loadlimit = (unsigned int) ceil(size * max_load_factor);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_init(&h->mutex, NULL);
+#endif
+ return h;
+}
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k)
+{
+ unsigned int i = h->hashfn(k);
+ i += ~(i << 9);
+ i ^= ((i >> 14) | (i << 18)); /* >>> */
+ i += (i << 4);
+ i ^= ((i >> 10) | (i << 22)); /* >>> */
+ return i;
+}
+
+/*****************************************************************************/
+static int
+hashtable_expand(struct hashtable *h)
+{
+ /* Double the size of the table to accomodate more entries */
+ struct entry **newtable;
+ struct entry *e;
+ struct entry **pE;
+ unsigned int newsize, i, index;
+ /* Check we're not hitting max capacity */
+ if (h->primeindex == (prime_table_length - 1)) return 0;
+ newsize = primes[++(h->primeindex)];
+
+ newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
+ if (NULL != newtable)
+ {
+ memset(newtable, 0, newsize * sizeof(struct entry *));
+ /* This algorithm is not 'stable'. ie. it reverses the list
+ * when it transfers entries between the tables */
+ for (i = 0; i < h->tablelength; i++) {
+ while (NULL != (e = h->table[i])) {
+ h->table[i] = e->next;
+ index = indexFor(newsize,e->h);
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ free(h->table);
+ h->table = newtable;
+ }
+ /* Plan B: realloc instead */
+ else
+ {
+ newtable = (struct entry **)
+ realloc(h->table, newsize * sizeof(struct entry *));
+ if (NULL == newtable) { (h->primeindex)--; return 0; }
+ h->table = newtable;
+ memset(newtable[h->tablelength], 0, newsize - h->tablelength);
+ for (i = 0; i < h->tablelength; i++) {
+ for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
+ index = indexFor(newsize,e->h);
+ if (index == i)
+ {
+ pE = &(e->next);
+ }
+ else
+ {
+ *pE = e->next;
+ e->next = newtable[index];
+ newtable[index] = e;
+ }
+ }
+ }
+ }
+ h->tablelength = newsize;
+ h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
+ return -1;
+}
+
+/*****************************************************************************/
+unsigned int
+hashtable_count(struct hashtable *h)
+{
+ unsigned int count;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ count = h->entrycount;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return count;
+}
+
+/*****************************************************************************/
+int
+hashtable_insert(struct hashtable *h, void *k, void *v)
+{
+ /* This method allows duplicate keys - but they shouldn't be used */
+ unsigned int index;
+ struct entry *e;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ if (++(h->entrycount) > h->loadlimit)
+ {
+ /* Ignore the return value. If expand fails, we should
+ * still try cramming just this value into the existing table
+ * -- we may not have memory for a larger table, but one more
+ * element may be ok. Next time we insert, we'll try expanding again.*/
+ hashtable_expand(h);
+ }
+ e = (struct entry *)malloc(sizeof(struct entry));
+ if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
+ e->h = hash(h,k);
+ index = indexFor(h->tablelength,e->h);
+ e->k = k;
+ e->v = v;
+ e->next = h->table[index];
+ h->table[index] = e;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return -1;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_search(struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e;
+ unsigned int hashvalue, index;
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+ e = h->table[index];
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return e->v;
+ }
+ e = e->next;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return NULL;
+}
+
+/*****************************************************************************/
+void * /* returns value associated with key */
+hashtable_remove(struct hashtable *h, void *k)
+{
+ /* TODO: consider compacting the table when the load factor drops enough,
+ * or provide a 'compact' method. */
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e;
+ struct entry **pE;
+ void *v;
+ unsigned int hashvalue, index;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hash(h,k));
+ pE = &(h->table[index]);
+ e = *pE;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ *pE = e->next;
+ h->entrycount--;
+ v = e->v;
+ freekey(e->k);
+ free(e);
+ return v;
+ }
+ pE = &(e->next);
+ e = e->next;
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return NULL;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h, int free_values)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+ if (free_values)
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
+ }
+ }
+ else
+ {
+ for (i = 0; i < h->tablelength; i++)
+ {
+ e = table[i];
+ while (NULL != e)
+ { f = e; e = e->next; freekey(f->k); free(f); }
+ }
+ }
+ free(h->table);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_destroy(&h->mutex);
+#endif
+ free(h);
+}
--- /dev/null
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@cl.cam.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_CWC22_H__
+#define __HASHTABLE_CWC22_H__
+
+struct hashtable;
+
+/* Example of use:
+ *
+ * struct hashtable *h;
+ * struct some_key *k;
+ * struct some_value *v;
+ *
+ * static unsigned int hash_from_key_fn( void *k );
+ * static int keys_equal_fn ( void *key1, void *key2 );
+ *
+ * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ * k = (struct some_key *) malloc(sizeof(struct some_key));
+ * v = (struct some_value *) malloc(sizeof(struct some_value));
+ *
+ * (initialise k and v to suitable values)
+ *
+ * if (! hashtable_insert(h,k,v) )
+ * { exit(-1); }
+ *
+ * if (NULL == (found = hashtable_search(h,k) ))
+ * { printf("not found!"); }
+ *
+ * if (NULL == (found = hashtable_remove(h,k) ))
+ * { printf("Not found\n"); }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ *
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/*****************************************************************************
+ * create_hashtable
+
+ * @name create_hashtable
+ * @param minsize minimum initial size of hashtable
+ * @param hashfunction function for hashing keys
+ * @param key_eq_fn function for determining key equality
+ * @return newly created hashtable or NULL on failure
+ */
+
+struct hashtable *
+create_hashtable(unsigned int minsize,
+ unsigned int (*hashfunction) (void*),
+ int (*key_eq_fn) (void*,void*));
+
+/*****************************************************************************
+ * hashtable_insert
+
+ * @name hashtable_insert
+ * @param h the hashtable to insert into
+ * @param k the key - hashtable claims ownership and will free on removal
+ * @param v the value - does not claim ownership
+ * @return non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+
+int
+hashtable_insert(struct hashtable *h, void *k, void *v);
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
+int fnname (struct hashtable *h, keytype *k, valuetype *v) \
+{ \
+ return hashtable_insert(h,k,v); \
+}
+
+/*****************************************************************************
+ * hashtable_search
+
+ * @name hashtable_search
+ * @param h the hashtable to search
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void *
+hashtable_search(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_search(h,k)); \
+}
+
+/*****************************************************************************
+ * hashtable_remove
+
+ * @name hashtable_remove
+ * @param h the hashtable to remove the item from
+ * @param k the key to search for - does not claim ownership
+ * @return the value associated with the key, or NULL if none found
+ */
+
+void * /* returns value */
+hashtable_remove(struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \
+valuetype * fnname (struct hashtable *h, keytype *k) \
+{ \
+ return (valuetype *) (hashtable_remove(h,k)); \
+}
+
+
+/*****************************************************************************
+ * hashtable_count
+
+ * @name hashtable_count
+ * @param h the hashtable
+ * @return the number of items stored in the hashtable
+ */
+unsigned int
+hashtable_count(struct hashtable *h);
+
+
+/*****************************************************************************
+ * hashtable_destroy
+
+ * @name hashtable_destroy
+ * @param h the hashtable
+ * @param free_values whether to call 'free' on the remaining values
+ */
+
+void
+hashtable_destroy(struct hashtable *h, int free_values);
+
+#endif /* __HASHTABLE_CWC22_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@cl.cam.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "hashtable.h"
+#include "hashtable_private.h"
+#include "hashtable_itr.h"
+#include <stdlib.h> /* defines NULL */
+
+/*****************************************************************************/
+/* hashtable_iterator - iterator constructor */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h)
+{
+ unsigned int i, tablelength;
+ struct hashtable_itr *itr = (struct hashtable_itr *)
+ malloc(sizeof(struct hashtable_itr));
+ if (NULL == itr) return NULL;
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ itr->h = h;
+ itr->e = NULL;
+ itr->parent = NULL;
+ tablelength = h->tablelength;
+ itr->index = tablelength;
+ if (0 == h->entrycount) {
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+ }
+
+ for (i = 0; i < tablelength; i++)
+ {
+ if (NULL != h->table[i])
+ {
+ itr->e = h->table[i];
+ itr->index = i;
+ break;
+ }
+ }
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&h->mutex);
+#endif
+ return itr;
+}
+
+/*****************************************************************************/
+/* key - return the key of the (key,value) pair at the current position */
+/* value - return the value of the (key,value) pair at the current position */
+
+void *
+hashtable_iterator_key(struct hashtable_itr *i)
+{ return i->e->k; }
+
+void *
+hashtable_iterator_value(struct hashtable_itr *i)
+{ return i->e->v; }
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ unsigned int j,tablelength;
+ struct entry **table;
+ struct entry *next;
+ int ret;
+ if (NULL == itr->e) { /* stupidity check */
+ ret = 0;
+ goto egress;
+ }
+
+ next = itr->e->next;
+ if (NULL != next)
+ {
+ itr->parent = itr->e;
+ itr->e = next;
+ ret = -1;
+ goto egress;
+ }
+
+ tablelength = itr->h->tablelength;
+ itr->parent = NULL;
+ if (tablelength <= (j = ++(itr->index)))
+ {
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ table = itr->h->table;
+ while (NULL == (next = table[j]))
+ {
+ if (++j >= tablelength)
+ {
+ itr->index = tablelength;
+ itr->e = NULL;
+ ret = 0;
+ goto egress;
+ }
+ }
+ itr->index = j;
+ itr->e = next;
+ ret = -1;
+
+ egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+/* remove - remove the entry at the current iterator position
+ * and advance the iterator, if there is a successive
+ * element.
+ * If you want the value, read it before you remove:
+ * beware memory leaks if you don't.
+ * Returns zero if end of iteration. */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&itr->h->mutex);
+#endif
+ struct entry *remember_e, *remember_parent;
+ int ret;
+
+ /* Do the removal */
+ if (NULL == (itr->parent))
+ {
+ /* element is head of a chain */
+ itr->h->table[itr->index] = itr->e->next;
+ } else {
+ /* element is mid-chain */
+ itr->parent->next = itr->e->next;
+ }
+ /* itr->e is now outside the hashtable */
+ remember_e = itr->e;
+ itr->h->entrycount--;
+ freekey(remember_e->k);
+
+ /* Advance the iterator, correcting the parent */
+ remember_parent = itr->parent;
+ ret = hashtable_iterator_advance(itr);
+ if (itr->parent == remember_e) { itr->parent = remember_parent; }
+ free(remember_e);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_unlock(&itr->h->mutex);
+#endif
+ return ret;
+}
+
+/*****************************************************************************/
+int /* returns zero if not found */
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k)
+{
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ struct entry *e, *parent;
+ unsigned int hashvalue, index;
+ int ret;
+
+ hashvalue = hash(h,k);
+ index = indexFor(h->tablelength,hashvalue);
+
+ e = h->table[index];
+ parent = NULL;
+ while (NULL != e)
+ {
+ /* Check hash value to short circuit heavier comparison */
+ if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
+ {
+ itr->index = index;
+ itr->e = e;
+ itr->parent = parent;
+ itr->h = h;
+ ret= -1;
+ goto egress;
+ }
+ parent = e;
+ e = e->next;
+ }
+ ret = 0;
+
+egress:
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_lock(&h->mutex);
+#endif
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@cl.cam.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HASHTABLE_ITR_CWC22__
+#define __HASHTABLE_ITR_CWC22__
+#include "hashtable.h"
+#include "hashtable_private.h" /* needed to enable inlining */
+
+/*****************************************************************************/
+/* This struct is only concrete here to allow the inlining of two of the
+ * accessor functions. */
+struct hashtable_itr
+{
+ struct hashtable *h;
+ struct entry *e;
+ struct entry *parent;
+ unsigned int index;
+};
+
+
+/*****************************************************************************/
+/* hashtable_iterator
+ */
+
+struct hashtable_itr *
+hashtable_iterator(struct hashtable *h);
+
+/*****************************************************************************/
+/* hashtable_iterator_key
+ * - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_key(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* value - return the value of the (key,value) pair at the current position */
+
+void *hashtable_iterator_value(struct hashtable_itr *i);
+
+/*****************************************************************************/
+/* advance - advance the iterator to the next element
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_advance(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* remove - remove current element and advance the iterator to the next element
+ * NB: if you need the value to free it, read it before
+ * removing. ie: beware memory leaks!
+ * returns zero if advanced to end of table */
+
+int
+hashtable_iterator_remove(struct hashtable_itr *itr);
+
+/*****************************************************************************/
+/* search - overwrite the supplied iterator, to point to the entry
+ * matching the supplied key.
+ h points to the hashtable to be searched.
+ * returns zero if not found. */
+int
+hashtable_iterator_search(struct hashtable_itr *itr,
+ struct hashtable *h, void *k);
+
+#define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \
+int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
+{ \
+ return (hashtable_iterator_search(i,h,k)); \
+}
+
+
+
+#endif /* __HASHTABLE_ITR_CWC22__*/
--- /dev/null
+/*
+ * Copyright (c) 2005, Intel Corp
+ * Copyright (c) 2002, Christopher Clark <firstname.lastname@cl.cam.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HASHTABLE_PRIVATE_CWC22_H__
+#define __HASHTABLE_PRIVATE_CWC22_H__
+
+#include "hashtable.h"
+#ifdef HASHTABLE_THREADED
+#include <pthread.h>
+#endif
+
+/*****************************************************************************/
+struct entry
+{
+ void *k, *v;
+ unsigned int h;
+ struct entry *next;
+};
+
+struct hashtable {
+ unsigned int tablelength;
+ struct entry **table;
+ unsigned int entrycount;
+ unsigned int loadlimit;
+ unsigned int primeindex;
+ unsigned int (*hashfn) (void *k);
+ int (*eqfn) (void *k1, void *k2);
+#ifdef HASHTABLE_THREADED
+ pthread_mutex_t mutex;
+#endif
+};
+
+/*****************************************************************************/
+unsigned int
+hash(struct hashtable *h, void *k);
+
+/*****************************************************************************/
+/* indexFor */
+static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue) {
+ return (hashvalue % tablelength);
+};
+
+/* Only works if tablelength == 2^N */
+/*static inline unsigned int
+indexFor(unsigned int tablelength, unsigned int hashvalue)
+{
+ return (hashvalue & (tablelength - 1u));
+}
+*/
+
+/*****************************************************************************/
+#define freekey(X) free(X)
+/*define freekey(X) ; */
+
+
+/*****************************************************************************/
+
+#endif /* __HASHTABLE_PRIVATE_CWC22_H__*/
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "buffer.h"
+#include "tcg.h"
+
+// Helper code for the consts, eg. to produce messages for error codes.
+
+typedef struct error_code_entry_t {
+ TPM_RESULT code;
+ char * code_name;
+ char * msg;
+} error_code_entry_t;
+
+static const error_code_entry_t error_msgs [] = {
+ { TPM_SUCCESS, "TPM_SUCCESS", "Successful completion of the operation" },
+ { TPM_AUTHFAIL, "TPM_AUTHFAIL", "Authentication failed" },
+ { TPM_BADINDEX, "TPM_BADINDEX", "The index to a PCR, DIR or other register is incorrect" },
+ { TPM_BAD_PARAMETER, "TPM_BAD_PARAMETER", "One or more parameter is bad" },
+ { TPM_AUDITFAILURE, "TPM_AUDITFAILURE", "An operation completed successfully but the auditing of that operation failed." },
+ { TPM_CLEAR_DISABLED, "TPM_CLEAR_DISABLED", "The clear disable flag is set and all clear operations now require physical access" },
+ { TPM_DEACTIVATED, "TPM_DEACTIVATED", "The TPM is deactivated" },
+ { TPM_DISABLED, "TPM_DISABLED", "The TPM is disabled" },
+ { TPM_DISABLED_CMD, "TPM_DISABLED_CMD", "The target command has been disabled" },
+ { TPM_FAIL, "TPM_FAIL", "The operation failed" },
+ { TPM_BAD_ORDINAL, "TPM_BAD_ORDINAL", "The ordinal was unknown or inconsistent" },
+ { TPM_INSTALL_DISABLED, "TPM_INSTALL_DISABLED", "The ability to install an owner is disabled" },
+ { TPM_INVALID_KEYHANDLE, "TPM_INVALID_KEYHANDLE", "The key handle presented was invalid" },
+ { TPM_KEYNOTFOUND, "TPM_KEYNOTFOUND", "The target key was not found" },
+ { TPM_INAPPROPRIATE_ENC, "TPM_INAPPROPRIATE_ENC", "Unacceptable encryption scheme" },
+ { TPM_MIGRATEFAIL, "TPM_MIGRATEFAIL", "Migration authorization failed" },
+ { TPM_INVALID_PCR_INFO, "TPM_INVALID_PCR_INFO", "PCR information could not be interpreted" },
+ { TPM_NOSPACE, "TPM_NOSPACE", "No room to load key." },
+ { TPM_NOSRK, "TPM_NOSRK", "There is no SRK set" },
+ { TPM_NOTSEALED_BLOB, "TPM_NOTSEALED_BLOB", "An encrypted blob is invalid or was not created by this TPM" },
+ { TPM_OWNER_SET, "TPM_OWNER_SET", "There is already an Owner" },
+ { TPM_RESOURCES, "TPM_RESOURCES", "The TPM has insufficient internal resources to perform the requested action." },
+ { TPM_SHORTRANDOM, "TPM_SHORTRANDOM", "A random string was too short" },
+ { TPM_SIZE, "TPM_SIZE", "The TPM does not have the space to perform the operation." },
+ { TPM_WRONGPCRVAL, "TPM_WRONGPCRVAL", "The named PCR value does not match the current PCR value." },
+ { TPM_BAD_PARAM_SIZE, "TPM_BAD_PARAM_SIZE", "The paramSize argument to the command has the incorrect value" },
+ { TPM_SHA_THREAD, "TPM_SHA_THREAD", "There is no existing SHA-1 thread." },
+ { TPM_SHA_ERROR, "TPM_SHA_ERROR", "The calculation is unable to proceed because the existing SHA-1 thread has already encountered an error." },
+ { TPM_FAILEDSELFTEST, "TPM_FAILEDSELFTEST", "Self-test has failed and the TPM has shutdown." },
+ { TPM_AUTH2FAIL, "TPM_AUTH2FAIL", "The authorization for the second key in a 2 key function failed authorization" },
+ { TPM_BADTAG, "TPM_BADTAG", "The tag value sent to for a command is invalid" },
+ { TPM_IOERROR, "TPM_IOERROR", "An IO error occurred transmitting information to the TPM" },
+ { TPM_ENCRYPT_ERROR, "TPM_ENCRYPT_ERROR", "The encryption process had a problem." },
+ { TPM_DECRYPT_ERROR, "TPM_DECRYPT_ERROR", "The decryption process did not complete." },
+ { TPM_INVALID_AUTHHANDLE, "TPM_INVALID_AUTHHANDLE", "An invalid handle was used." },
+ { TPM_NO_ENDORSEMENT, "TPM_NO_ENDORSEMENT", "The TPM does not a EK installed" },
+ { TPM_INVALID_KEYUSAGE, "TPM_INVALID_KEYUSAGE", "The usage of a key is not allowed" },
+ { TPM_WRONG_ENTITYTYPE, "TPM_WRONG_ENTITYTYPE", "The submitted entity type is not allowed" },
+ { TPM_INVALID_POSTINIT, "TPM_INVALID_POSTINIT", "The command was received in the wrong sequence relative to TPM_Init and a subsequent TPM_Startup" },
+ { TPM_INAPPROPRIATE_SIG, "TPM_INAPPROPRIATE_SIG", "Signed data cannot include additional DER information" },
+ { TPM_BAD_KEY_PROPERTY, "TPM_BAD_KEY_PROPERTY", "The key properties in TPM_KEY_PARMs are not supported by this TPM" },
+
+ { TPM_BAD_MIGRATION, "TPM_BAD_MIGRATION", "The migration properties of this key are incorrect." },
+ { TPM_BAD_SCHEME, "TPM_BAD_SCHEME", "The signature or encryption scheme for this key is incorrect or not permitted in this situation." },
+ { TPM_BAD_DATASIZE, "TPM_BAD_DATASIZE", "The size of the data (or blob) parameter is bad or inconsistent with the referenced key" },
+ { TPM_BAD_MODE, "TPM_BAD_MODE", "A mode parameter is bad, such as capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob." },
+ { TPM_BAD_PRESENCE, "TPM_BAD_PRESENCE", "Either the physicalPresence or physicalPresenceLock bits have the wrong value" },
+ { TPM_BAD_VERSION, "TPM_BAD_VERSION", "The TPM cannot perform this version of the capability" },
+ { TPM_NO_WRAP_TRANSPORT, "TPM_NO_WRAP_TRANSPORT", "The TPM does not allow for wrapped transport sessions" },
+ { TPM_AUDITFAIL_UNSUCCESSFUL, "TPM_AUDITFAIL_UNSUCCESSFUL", "TPM audit construction failed and the underlying command was returning a failure code also" },
+ { TPM_AUDITFAIL_SUCCESSFUL, "TPM_AUDITFAIL_SUCCESSFUL", "TPM audit construction failed and the underlying command was returning success" },
+ { TPM_NOTRESETABLE, "TPM_NOTRESETABLE", "Attempt to reset a PCR register that does not have the resettable attribute" },
+ { TPM_NOTLOCAL, "TPM_NOTLOCAL", "Attempt to reset a PCR register that requires locality and locality modifier not part of command transport" },
+ { TPM_BAD_TYPE, "TPM_BAD_TYPE", "Make identity blob not properly typed" },
+ { TPM_INVALID_RESOURCE, "TPM_INVALID_RESOURCE", "When saving context identified resource type does not match actual resource" },
+ { TPM_NOTFIPS, "TPM_NOTFIPS", "The TPM is attempting to execute a command only available when in FIPS mode" },
+ { TPM_INVALID_FAMILY, "TPM_INVALID_FAMILY", "The command is attempting to use an invalid family ID" },
+ { TPM_NO_NV_PERMISSION, "TPM_NO_NV_PERMISSION", "The permission to manipulate the NV storage is not available" },
+ { TPM_REQUIRES_SIGN, "TPM_REQUIRES_SIGN", "The operation requires a signed command" },
+ { TPM_KEY_NOTSUPPORTED, "TPM_KEY_NOTSUPPORTED", "Wrong operation to load an NV key" },
+ { TPM_AUTH_CONFLICT, "TPM_AUTH_CONFLICT", "NV_LoadKey blob requires both owner and blob authorization" },
+ { TPM_AREA_LOCKED, "TPM_AREA_LOCKED", "The NV area is locked and not writtable" },
+ { TPM_BAD_LOCALITY, "TPM_BAD_LOCALITY", "The locality is incorrect for the attempted operation" },
+ { TPM_READ_ONLY, "TPM_READ_ONLY", "The NV area is read only and can't be written to" },
+ { TPM_PER_NOWRITE, "TPM_PER_NOWRITE", "There is no protection on the write to the NV area" },
+ { TPM_FAMILYCOUNT, "TPM_FAMILYCOUNT", "The family count value does not match" },
+ { TPM_WRITE_LOCKED, "TPM_WRITE_LOCKED", "The NV area has already been written to" },
+ { TPM_BAD_ATTRIBUTES, "TPM_BAD_ATTRIBUTES", "The NV area attributes conflict" },
+ { TPM_INVALID_STRUCTURE, "TPM_INVALID_STRUCTURE", "The structure tag and version are invalid or inconsistent" },
+ { TPM_KEY_OWNER_CONTROL, "TPM_KEY_OWNER_CONTROL", "The key is under control of the TPM Owner and can only be evicted by the TPM Owner." },
+ { TPM_BAD_COUNTER, "TPM_BAD_COUNTER", "The counter handle is incorrect" },
+ { TPM_NOT_FULLWRITE, "TPM_NOT_FULLWRITE", "The write is not a complete write of the area" },
+ { TPM_CONTEXT_GAP, "TPM_CONTEXT_GAP", "The gap between saved context counts is too large" },
+ { TPM_MAXNVWRITES, "TPM_MAXNVWRITES", "The maximum number of NV writes without an owner has been exceeded" },
+ { TPM_NOOPERATOR, "TPM_NOOPERATOR", "No operator authorization value is set" },
+ { TPM_RESOURCEMISSING, "TPM_RESOURCEMISSING", "The resource pointed to by context is not loaded" },
+ { TPM_DELEGATE_LOCK, "TPM_DELEGATE_LOCK", "The delegate administration is locked" },
+ { TPM_DELEGATE_FAMILY, "TPM_DELEGATE_FAMILY", "Attempt to manage a family other then the delegated family" },
+ { TPM_DELEGATE_ADMIN, "TPM_DELEGATE_ADMIN", "Delegation table management not enabled" },
+ { TPM_TRANSPORT_EXCLUSIVE, "TPM_TRANSPORT_EXCLUSIVE", "There was a command executed outside of an exclusive transport session" },
+};
+
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code) {
+ // just do a linear scan for now
+ unsigned i;
+ for (i = 0; i < sizeof(error_msgs)/sizeof(error_msgs[0]); i++)
+ if (code == error_msgs[i].code)
+ return error_msgs[i].code_name;
+
+ return "Failed to find code name for given code";
+}
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+
+#ifndef __VTPM_LOG_H__
+#define __VTPM_LOG_H__
+
+#include <stdint.h> // for uint32_t
+#include <stddef.h> // for pointer NULL
+
+// =========================== LOGGING ==============================
+
+// the logging module numbers
+#define VTPM_LOG_CRYPTO 1
+#define VTPM_LOG_BSG 2
+#define VTPM_LOG_TXDATA 3
+#define VTPM_LOG_TCS 4
+#define VTPM_LOG_TCS_DEEP 5
+#define VTPM_LOG_VTSP 6
+#define VTPM_LOG_VTPM 7
+#define VTPM_LOG_VTPM_DEEP 8
+
+static char *module_names[] = { "",
+ "CRYPTO",
+ "BSG",
+ "TXDATA",
+ "TCS",
+ "TCS",
+ "VTSP",
+ "VTPM",
+ "VTPM"
+ };
+
+// Default to standard logging
+#ifndef LOGGING_MODULES
+#define LOGGING_MODULES (BITMASK(VTPM_LOG_VTPM))
+#endif
+
+// bit-access macros
+#define BITMASK(idx) ( 1U << (idx) )
+#define GETBIT(num,idx) ( ((num) & BITMASK(idx)) >> idx )
+#define SETBIT(num,idx) (num) |= BITMASK(idx)
+#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) )
+
+#define vtpmloginfo(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \
+ }
+
+#define vtpmloginfomore(module, fmt, args...) \
+ if (GETBIT (LOGGING_MODULES, module) == 1) { \
+ fprintf (stdout, fmt,##args); \
+ }
+
+#define vtpmlogerror(module, fmt, args...) \
+ fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args);
+
+//typedef UINT32 tpm_size_t;
+
+// helper function for the error codes:
+const char* tpm_get_error_name (TPM_RESULT code);
+
+#endif // _VTPM_LOG_H_
--- /dev/null
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// tcg.h
+//
+// This file contains all the structure and type definitions
+//
+// ==================================================================
+
+#ifndef __TCG_H__
+#define __TCG_H__
+
+// This pragma is used to disallow structure padding
+#pragma pack(push, 1)
+
+// *************************** TYPEDEFS *********************************
+typedef unsigned char BYTE;
+typedef unsigned char BOOL;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+typedef UINT32 TPM_RESULT;
+typedef UINT32 TPM_PCRINDEX;
+typedef UINT32 TPM_DIRINDEX;
+typedef UINT32 TPM_HANDLE;
+typedef TPM_HANDLE TPM_AUTHHANDLE;
+typedef TPM_HANDLE TCPA_HASHHANDLE;
+typedef TPM_HANDLE TCPA_HMACHANDLE;
+typedef TPM_HANDLE TCPA_ENCHANDLE;
+typedef TPM_HANDLE TPM_KEY_HANDLE;
+typedef TPM_HANDLE TCPA_ENTITYHANDLE;
+typedef UINT32 TPM_RESOURCE_TYPE;
+typedef UINT32 TPM_COMMAND_CODE;
+typedef UINT16 TPM_PROTOCOL_ID;
+typedef BYTE TPM_AUTH_DATA_USAGE;
+typedef UINT16 TPM_ENTITY_TYPE;
+typedef UINT32 TPM_ALGORITHM_ID;
+typedef UINT16 TPM_KEY_USAGE;
+typedef UINT16 TPM_STARTUP_TYPE;
+typedef UINT32 TPM_CAPABILITY_AREA;
+typedef UINT16 TPM_ENC_SCHEME;
+typedef UINT16 TPM_SIG_SCHEME;
+typedef UINT16 TPM_MIGRATE_SCHEME;
+typedef UINT16 TPM_PHYSICAL_PRESENCE;
+typedef UINT32 TPM_KEY_FLAGS;
+
+#define TPM_DIGEST_SIZE 20 // Don't change this
+typedef BYTE TPM_AUTHDATA[TPM_DIGEST_SIZE];
+typedef TPM_AUTHDATA TPM_SECRET;
+typedef TPM_AUTHDATA TPM_ENCAUTH;
+typedef BYTE TPM_PAYLOAD_TYPE;
+typedef UINT16 TPM_TAG;
+
+// Data Types of the TCS
+typedef UINT32 TCS_AUTHHANDLE; // Handle addressing a authorization session
+typedef UINT32 TCS_CONTEXT_HANDLE; // Basic context handle
+typedef UINT32 TCS_KEY_HANDLE; // Basic key handle
+
+// ************************* STRUCTURES **********************************
+
+typedef struct TPM_VERSION {
+ BYTE major;
+ BYTE minor;
+ BYTE revMajor;
+ BYTE revMinor;
+} TPM_VERSION;
+
+static const TPM_VERSION TPM_STRUCT_VER_1_1 = { 1,1,0,0 };
+
+typedef struct TPM_DIGEST {
+ BYTE digest[TPM_DIGEST_SIZE];
+} TPM_DIGEST;
+
+typedef TPM_DIGEST TPM_PCRVALUE;
+typedef TPM_DIGEST TPM_COMPOSITE_HASH;
+typedef TPM_DIGEST TPM_DIRVALUE;
+typedef TPM_DIGEST TPM_HMAC;
+typedef TPM_DIGEST TPM_CHOSENID_HASH;
+
+typedef struct TPM_NONCE {
+ BYTE nonce[TPM_DIGEST_SIZE];
+} TPM_NONCE;
+
+typedef struct TPM_KEY_PARMS {
+ TPM_ALGORITHM_ID algorithmID;
+ TPM_ENC_SCHEME encScheme;
+ TPM_SIG_SCHEME sigScheme;
+ UINT32 parmSize;
+ BYTE* parms;
+} TPM_KEY_PARMS;
+
+typedef struct TPM_RSA_KEY_PARMS {
+ UINT32 keyLength;
+ UINT32 numPrimes;
+ UINT32 exponentSize;
+ BYTE* exponent;
+} TPM_RSA_KEY_PARMS;
+
+typedef struct TPM_STORE_PUBKEY {
+ UINT32 keyLength;
+ BYTE* key;
+} TPM_STORE_PUBKEY;
+
+typedef struct TPM_PUBKEY {
+ TPM_KEY_PARMS algorithmParms;
+ TPM_STORE_PUBKEY pubKey;
+} TPM_PUBKEY;
+
+typedef struct TPM_KEY {
+ TPM_VERSION ver;
+ TPM_KEY_USAGE keyUsage;
+ TPM_KEY_FLAGS keyFlags;
+ TPM_AUTH_DATA_USAGE authDataUsage;
+ TPM_KEY_PARMS algorithmParms;
+ UINT32 PCRInfoSize;
+ BYTE* PCRInfo; // this should be a TPM_PCR_INFO, or NULL
+ TPM_STORE_PUBKEY pubKey;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_KEY;
+
+typedef struct TPM_PCR_SELECTION {
+ UINT16 sizeOfSelect; /// in bytes
+ BYTE* pcrSelect;
+} TPM_PCR_SELECTION;
+
+typedef struct TPM_PCR_COMPOSITE {
+ TPM_PCR_SELECTION select;
+ UINT32 valueSize;
+ TPM_PCRVALUE* pcrValue;
+} TPM_PCR_COMPOSITE;
+
+
+typedef struct TPM_PCR_INFO {
+ TPM_PCR_SELECTION pcrSelection;
+ TPM_COMPOSITE_HASH digestAtRelease;
+ TPM_COMPOSITE_HASH digestAtCreation;
+} TPM_PCR_INFO;
+
+
+typedef struct TPM_BOUND_DATA {
+ TPM_VERSION ver;
+ TPM_PAYLOAD_TYPE payload;
+ BYTE* payloadData;
+} TPM_BOUND_DATA;
+
+typedef struct TPM_STORED_DATA {
+ TPM_VERSION ver;
+ UINT32 sealInfoSize;
+ BYTE* sealInfo;
+ UINT32 encDataSize;
+ BYTE* encData;
+} TPM_STORED_DATA;
+
+typedef struct TCS_AUTH {
+ TCS_AUTHHANDLE AuthHandle;
+ TPM_NONCE NonceOdd; // system
+ TPM_NONCE NonceEven; // TPM
+ BOOL fContinueAuthSession;
+ TPM_AUTHDATA HMAC;
+} TCS_AUTH;
+
+// **************************** CONSTANTS *********************************
+
+// BOOL values
+#define TRUE 0x01
+#define FALSE 0x00
+
+#define TCPA_MAX_BUFFER_LENGTH 0x2000
+
+//
+// TPM_COMMAND_CODE values
+#define TPM_PROTECTED_ORDINAL 0x00000000UL
+#define TPM_UNPROTECTED_ORDINAL 0x80000000UL
+#define TPM_CONNECTION_ORDINAL 0x40000000UL
+#define TPM_VENDOR_ORDINAL 0x20000000UL
+
+#define TPM_ORD_OIAP (10UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OSAP (11UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuth (12UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_TakeOwnership (13UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymStart (14UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthAsymFinish (15UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ChangeAuthOwner (16UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Extend (20UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PcrRead (21UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Quote (22UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Seal (23UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Unseal (24UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirWriteAuth (25UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DirRead (26UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_UnBind (30UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateWrapKey (31UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKey (32UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetPubKey (33UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_EvictKey (34UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMigrationBlob (40UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReWrapKey (41UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ConvertMigrationBlob (42UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_AuthorizeMigrationKey (43UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateMaintenanceArchive (44UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadMaintenanceArchive (45UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_KillMaintenanceFeature (46UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadManuMaintPub (47UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadManuMaintPub (48UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifyKey (50UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Sign (60UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetRandom (70UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_StirRandom (71UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestFull (80UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SelfTestStartup (81UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CertifySelfTest (82UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ContinueSelfTest (83UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetTestResult (84UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Reset (90UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerClear (91UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableOwnerClear (92UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ForceClear (93UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisableForceClear (94UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilitySigned (100UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapability (101UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetCapabilityOwner (102UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerSetDisable (110UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalEnable (111UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalDisable (112UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOwnerInstall (113UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PhysicalSetDeactivated (114UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetTempDeactivated (115UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateEndorsementKeyPair (120UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_MakeIdentity (121UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ActivateIdentity (122UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadPubek (124UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_OwnerReadPubek (125UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_DisablePubekRead (126UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEvent (130UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetAuditEventSigned (131UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetOrdinalAuditStatus (140UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetOrdinalAuditStatus (141UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Terminate_Handle (150UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Init (151UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveState (152UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Startup (153UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SetRedirection (154UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Start (160UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Update (161UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1Complete (162UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SHA1CompleteExtend (163UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_FieldUpgrade (170UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveKeyContext (180UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadKeyContext (181UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveAuthContext (182UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadAuthContext (183UL + TPM_PROTECTED_ORDINAL)
+#define TSC_ORD_PhysicalPresence (10UL + TPM_CONNECTION_ORDINAL)
+
+
+
+//
+// TPM_RESULT values
+//
+// just put in the whole table from spec 1.2
+
+#define TPM_BASE 0x0 // The start of TPM return codes
+#define TPM_VENDOR_ERROR 0x00000400 // Mask to indicate that the error code is vendor specific for vendor specific commands
+#define TPM_NON_FATAL 0x00000800 // Mask to indicate that the error code is a non-fatal failure.
+
+#define TPM_SUCCESS TPM_BASE // Successful completion of the operation
+#define TPM_AUTHFAIL TPM_BASE + 1 // Authentication failed
+#define TPM_BADINDEX TPM_BASE + 2 // The index to a PCR, DIR or other register is incorrect
+#define TPM_BAD_PARAMETER TPM_BASE + 3 // One or more parameter is bad
+#define TPM_AUDITFAILURE TPM_BASE + 4 // An operation completed successfully but the auditing of that operation failed.
+#define TPM_CLEAR_DISABLED TPM_BASE + 5 // The clear disable flag is set and all clear operations now require physical access
+#define TPM_DEACTIVATED TPM_BASE + 6 // The TPM is deactivated
+#define TPM_DISABLED TPM_BASE + 7 // The TPM is disabled
+#define TPM_DISABLED_CMD TPM_BASE + 8 // The target command has been disabled
+#define TPM_FAIL TPM_BASE + 9 // The operation failed
+#define TPM_BAD_ORDINAL TPM_BASE + 10 // The ordinal was unknown or inconsistent
+#define TPM_INSTALL_DISABLED TPM_BASE + 11 // The ability to install an owner is disabled
+#define TPM_INVALID_KEYHANDLE TPM_BASE + 12 // The key handle presented was invalid
+#define TPM_KEYNOTFOUND TPM_BASE + 13 // The target key was not found
+#define TPM_INAPPROPRIATE_ENC TPM_BASE + 14 // Unacceptable encryption scheme
+#define TPM_MIGRATEFAIL TPM_BASE + 15 // Migration authorization failed
+#define TPM_INVALID_PCR_INFO TPM_BASE + 16 // PCR information could not be interpreted
+#define TPM_NOSPACE TPM_BASE + 17 // No room to load key.
+#define TPM_NOSRK TPM_BASE + 18 // There is no SRK set
+#define TPM_NOTSEALED_BLOB TPM_BASE + 19 // An encrypted blob is invalid or was not created by this TPM
+#define TPM_OWNER_SET TPM_BASE + 20 // There is already an Owner
+#define TPM_RESOURCES TPM_BASE + 21 // The TPM has insufficient internal resources to perform the requested action.
+#define TPM_SHORTRANDOM TPM_BASE + 22 // A random string was too short
+#define TPM_SIZE TPM_BASE + 23 // The TPM does not have the space to perform the operation.
+#define TPM_WRONGPCRVAL TPM_BASE + 24 // The named PCR value does not match the current PCR value.
+#define TPM_BAD_PARAM_SIZE TPM_BASE + 25 // The paramSize argument to the command has the incorrect value
+#define TPM_SHA_THREAD TPM_BASE + 26 // There is no existing SHA-1 thread.
+#define TPM_SHA_ERROR TPM_BASE + 27 // The calculation is unable to proceed because the existing SHA-1 thread has already encountered an error.
+#define TPM_FAILEDSELFTEST TPM_BASE + 28 // Self-test has failed and the TPM has shutdown.
+#define TPM_AUTH2FAIL TPM_BASE + 29 // The authorization for the second key in a 2 key function failed authorization
+#define TPM_BADTAG TPM_BASE + 30 // The tag value sent to for a command is invalid
+#define TPM_IOERROR TPM_BASE + 31 // An IO error occurred transmitting information to the TPM
+#define TPM_ENCRYPT_ERROR TPM_BASE + 32 // The encryption process had a problem.
+#define TPM_DECRYPT_ERROR TPM_BASE + 33 // The decryption process did not complete.
+#define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 // An invalid handle was used.
+#define TPM_NO_ENDORSEMENT TPM_BASE + 35 // The TPM does not a EK installed
+#define TPM_INVALID_KEYUSAGE TPM_BASE + 36 // The usage of a key is not allowed
+#define TPM_WRONG_ENTITYTYPE TPM_BASE + 37 // The submitted entity type is not allowed
+#define TPM_INVALID_POSTINIT TPM_BASE + 38 // The command was received in the wrong sequence relative to TPM_Init and a subsequent TPM_Startup
+#define TPM_INAPPROPRIATE_SIG TPM_BASE + 39 // Signed data cannot include additional DER information
+#define TPM_BAD_KEY_PROPERTY TPM_BASE + 40 // The key properties in TPM_KEY_PARMs are not supported by this TPM
+
+#define TPM_BAD_MIGRATION TPM_BASE + 41 // The migration properties of this key are incorrect.
+#define TPM_BAD_SCHEME TPM_BASE + 42 // The signature or encryption scheme for this key is incorrect or not permitted in this situation.
+#define TPM_BAD_DATASIZE TPM_BASE + 43 // The size of the data (or blob) parameter is bad or inconsistent with the referenced key
+#define TPM_BAD_MODE TPM_BASE + 44 // A mode parameter is bad, such as capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob.
+#define TPM_BAD_PRESENCE TPM_BASE + 45 // Either the physicalPresence or physicalPresenceLock bits have the wrong value
+#define TPM_BAD_VERSION TPM_BASE + 46 // The TPM cannot perform this version of the capability
+#define TPM_NO_WRAP_TRANSPORT TPM_BASE + 47 // The TPM does not allow for wrapped transport sessions
+#define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 // TPM audit construction failed and the underlying command was returning a failure code also
+#define TPM_AUDITFAIL_SUCCESSFUL TPM_BASE + 49 // TPM audit construction failed and the underlying command was returning success
+#define TPM_NOTRESETABLE TPM_BASE + 50 // Attempt to reset a PCR register that does not have the resettable attribute
+#define TPM_NOTLOCAL TPM_BASE + 51 // Attempt to reset a PCR register that requires locality and locality modifier not part of command transport
+#define TPM_BAD_TYPE TPM_BASE + 52 // Make identity blob not properly typed
+#define TPM_INVALID_RESOURCE TPM_BASE + 53 // When saving context identified resource type does not match actual resource
+#define TPM_NOTFIPS TPM_BASE + 54 // The TPM is attempting to execute a command only available when in FIPS mode
+#define TPM_INVALID_FAMILY TPM_BASE + 55 // The command is attempting to use an invalid family ID
+#define TPM_NO_NV_PERMISSION TPM_BASE + 56 // The permission to manipulate the NV storage is not available
+#define TPM_REQUIRES_SIGN TPM_BASE + 57 // The operation requires a signed command
+#define TPM_KEY_NOTSUPPORTED TPM_BASE + 58 // Wrong operation to load an NV key
+#define TPM_AUTH_CONFLICT TPM_BASE + 59 // NV_LoadKey blob requires both owner and blob authorization
+#define TPM_AREA_LOCKED TPM_BASE + 60 // The NV area is locked and not writtable
+#define TPM_BAD_LOCALITY TPM_BASE + 61 // The locality is incorrect for the attempted operation
+#define TPM_READ_ONLY TPM_BASE + 62 // The NV area is read only and can't be written to
+#define TPM_PER_NOWRITE TPM_BASE + 63 // There is no protection on the write to the NV area
+#define TPM_FAMILYCOUNT TPM_BASE + 64 // The family count value does not match
+#define TPM_WRITE_LOCKED TPM_BASE + 65 // The NV area has already been written to
+#define TPM_BAD_ATTRIBUTES TPM_BASE + 66 // The NV area attributes conflict
+#define TPM_INVALID_STRUCTURE TPM_BASE + 67 // The structure tag and version are invalid or inconsistent
+#define TPM_KEY_OWNER_CONTROL TPM_BASE + 68 // The key is under control of the TPM Owner and can only be evicted by the TPM Owner.
+#define TPM_BAD_COUNTER TPM_BASE + 69 // The counter handle is incorrect
+#define TPM_NOT_FULLWRITE TPM_BASE + 70 // The write is not a complete write of the area
+#define TPM_CONTEXT_GAP TPM_BASE + 71 // The gap between saved context counts is too large
+#define TPM_MAXNVWRITES TPM_BASE + 72 // The maximum number of NV writes without an owner has been exceeded
+#define TPM_NOOPERATOR TPM_BASE + 73 // No operator authorization value is set
+#define TPM_RESOURCEMISSING TPM_BASE + 74 // The resource pointed to by context is not loaded
+#define TPM_DELEGATE_LOCK TPM_BASE + 75 // The delegate administration is locked
+#define TPM_DELEGATE_FAMILY TPM_BASE + 76 // Attempt to manage a family other then the delegated family
+#define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management not enabled
+#define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command executed outside of an exclusive transport session
+
+// TPM_TAG values
+#define TPM_TAG_RQU_COMMAND 0x00c1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3
+#define TPM_TAG_RSP_COMMAND 0x00c4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00c5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00c6
+
+// TPM_PAYLOAD_TYPE values
+#define TPM_PT_ASYM 0x01
+#define TPM_PT_BIND 0x02
+#define TPM_PT_MIGRATE 0x03
+#define TPM_PT_MAINT 0x04
+#define TPM_PT_SEAL 0x05
+
+// TPM_ENTITY_TYPE values
+#define TPM_ET_KEYHANDLE 0x0001
+#define TPM_ET_OWNER 0x0002
+#define TPM_ET_DATA 0x0003
+#define TPM_ET_SRK 0x0004
+#define TPM_ET_KEY 0x0005
+
+/// TPM_ResourceTypes
+#define TPM_RT_KEY 0x00000001
+#define TPM_RT_AUTH 0x00000002
+#define TPM_RT_TRANS 0x00000004
+#define TPM_RT_CONTEXT 0x00000005
+
+// TPM_PROTOCOL_ID values
+#define TPM_PID_OIAP 0x0001
+#define TPM_PID_OSAP 0x0002
+#define TPM_PID_ADIP 0x0003
+#define TPM_PID_ADCP 0x0004
+#define TPM_PID_OWNER 0x0005
+
+// TPM_ALGORITHM_ID values
+#define TPM_ALG_RSA 0x00000001
+#define TPM_ALG_DES 0x00000002
+#define TPM_ALG_3DES 0X00000003
+#define TPM_ALG_SHA 0x00000004
+#define TPM_ALG_HMAC 0x00000005
+#define TCPA_ALG_AES 0x00000006
+
+// TPM_ENC_SCHEME values
+#define TPM_ES_NONE 0x0001
+#define TPM_ES_RSAESPKCSv15 0x0002
+#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003
+
+// TPM_SIG_SCHEME values
+#define TPM_SS_NONE 0x0001
+#define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002
+#define TPM_SS_RSASSAPKCS1v15_DER 0x0003
+
+// TPM_KEY_USAGE values
+#define TPM_KEY_EK 0x0000
+#define TPM_KEY_SIGNING 0x0010
+#define TPM_KEY_STORAGE 0x0011
+#define TPM_KEY_IDENTITY 0x0012
+#define TPM_KEY_AUTHCHANGE 0X0013
+#define TPM_KEY_BIND 0x0014
+#define TPM_KEY_LEGACY 0x0015
+
+// TPM_AUTH_DATA_USAGE values
+#define TPM_AUTH_NEVER 0x00
+#define TPM_AUTH_ALWAYS 0x01
+
+// Key Handle of owner and srk
+#define TPM_OWNER_KEYHANDLE 0x40000001
+#define TPM_SRK_KEYHANDLE 0x40000000
+
+// ---------------------- Functions for checking TPM_RESULTs -----------------
+
+// FIXME: Review use of these and delete unneeded ones.
+
+// these are really badly dependent on local structure:
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+#define ERRORDIE(s) do { status = s; \
+ fprintf (stderr, "*** ERRORDIE in %s, line %i\n", __func__, __LINE__); \
+ goto abort_egress; } \
+ while (0)
+
+// ASSUME: the return value used after the abort_egress label has been set
+// already (eg. the 'status' local var)
+#define STATUSCHECK(s) if (s != TPM_SUCCESS) { \
+ fprintf (stderr, "*** ERR in %s, line %i\n", __func__, __LINE__); \
+ goto abort_egress; \
+ }
+
+// DEPENDS: local var 'status' of type TPM_RESULT
+// DEPENDS: label 'abort_egress' which cleans up and returns the status
+// Try command c. If it fails, set status to s and goto shame.
+#define TPMTRY(s,c) if (c != TPM_SUCCESS) { \
+ status = s; \
+ goto abort_egress; \
+ }
+
+// Try command c. If it fails, print error message, set status to actual return code. Goto shame
+#define TPMTRYRETURN(c) do { status = c; \
+ if (status != TPM_SUCCESS) { \
+ printf("ERROR in %s:%i code: %s.\n", __func__, __LINE__, tpm_get_error_name(status)); \
+ goto abort_egress; \
+ } \
+ } while(0)
+
+
+#pragma pack(pop)
+
+#endif //__TCPA_H__